LoopBack4: доступ к репозиторию внутри перехватчика

Я хотел бы улучшить перехватчик в моем приложении LoopBack4, которое в настоящее время просто выводит мне начало и конец вызова метода контроллера в командной строке, как описано здесь: https://loopback.io/doc/en/lb4/Interceptors.html

Мой журнал-перехватчик выглядит так:

export const Log: Interceptor = async (invocationCtx, next) => {
    // Wait until the interceptor/method chain returns
    const req = await invocationCtx.get(RestBindings.Http.REQUEST);

    try
    {
        const stackinfo = 'Class: ' + invocationCtx.targetClass.name + ' | Method: ' + invocationCtx.methodName + " | Request IPs: " + req.ips.concat(', ');

        logger.trace('Starting - ' + stackinfo);

        const result = await next();
        const res = await invocationCtx.get(RestBindings.Http.RESPONSE);

        logger.trace('Ending - ' + stackinfo + ' | Response Status Code: ' + res.statusCode);

        return result;
    }
    catch (e)
    {
        logger.error(e);
        throw e;
    }
};

Теперь я хотел бы улучшить этот перехватчик, чтобы он также регистрировал некоторые статистические данные в моем источнике данных MySQL. Моя проблема в том, как я могу получить доступ к хранилищу внутри перехватчика? Нужно ли мне вводить репозиторий, и если да, то как мне это делать? Или есть лучший способ добиться этого?


person MIB    schedule 30.09.2019    source источник


Ответы (2)


Я нашел решение самостоятельно:

  1. создать услугу:
export class StatisticService
{
    constructor(
        @repository(StatisticRecordRepository) public statisticsRepository: StatisticRecordRepository
    ) {}


    async increment(key: string, addend = 1): Promise<void>
    {
        const existing = await this.statisticsRepository.findOne({where: {StatsKey: key}});
        if(existing !== null)
        {
            // @ts-ignore
            existing.Counter = existing.Counter + addend;
            existing.UpdateTs = (new Date()).toISOString();
            await this.statisticsRepository.update(existing);
        }
        else
        {
            await this.statisticsRepository.create(new StatisticRecord({
                                                                           StatsKey: key,
                                                                           Counter:  addend
                                                                       }));
        }
    }
}


export const StatisticsServiceBindings = {
    VALUE: BindingKey.create<StatisticService>("services.StatisticsService")
};
  1. привяжите службу в конструкторе приложения:
this.bind(StatisticsServiceBindings.VALUE).toClass(StatisticService);
  1. получить и использовать Сервис в Log-Interceptor:
const stats = await invocationCtx.get(StatisticsServiceBindings.VALUE);
stats.increment(invocationCtx.targetClass.name + '::' + invocationCtx.methodName + ' [' + res.statusCode + ']');
person MIB    schedule 30.09.2019

Вы можете получить доступ к репозиториям в ваших перехватчиках через invocationCtx.target следующим образом:

export const exampleInterceptor: Interceptor = async (invocationCtx, next) => {
  const exampleRepo = invocationCtx.target.exampleRepository;
  const anotherExampleRepo = invocationCtx.target.anotherExampleRepository;
};

учитывая, что у вас есть соответствующие декораторы @repository в контроллере, где будет ваш перехватчик (работает с перехватчиками как на уровне класса, так и на уровне метода)

@intercept(exampleInterceptor)
export class ExampleController {
  constructor(
    @repository(ExampleRepository)
    public exampleRepository: ExampleRepository,
    @repository(AnotherExampleRepository)
    public anotherExampleRepository: AnotherExampleRepository
  ) {}
}

Не уверен, что это рекомендуемое решение. Хотел бы услышать другие предложения.

person David    schedule 25.04.2020