NestJS: Как зарегистрировать временные и веб-провайдеры - PullRequest
0 голосов
/ 08 декабря 2018

Я работаю над мультитенантным приложением, использующим NestJS, и предлагаю свой API через модуль GraphQL.Я хотел бы знать, как я могу сказать NestJS создавать экземпляры моих провайдеров для каждого веб-запроса.В соответствии с их документацией поставщики по умолчанию являются одиночными, но я не смог найти способ зарегистрировать временных или индивидуальных поставщиков.

Позвольте мне объяснить конкретный вариант использования для этого.В моей мультитенантной реализации у меня есть база данных для каждого клиента, и каждый раз, когда я получаю запрос в бэкэнде, мне нужно выяснить, для какого клиента это нужно, и мне нужно создавать экземпляры служб с подключением к нужной базе данных.

Возможно ли это даже с помощью NestJS?

Ответы [ 2 ]

0 голосов
/ 08 декабря 2018

С выпуском nest.js 6.0 были добавлены области инъекций .При этом вы можете выбрать одну из следующих трех областей для своих провайдеров:

  • SINGLETON : поведение по умолчанию.Один экземпляр вашего провайдера используется для всего приложения
  • TRANSIENT : выделенный экземпляр вашего провайдера создается для каждого провайдера, который его внедряет.
  • ЗАПРОС: для каждого запроса создается новый поставщик.Внимание: это поведение будет всплывать в вашей цепочке зависимостей.Пример: если UsersController (Singleton) внедряет UsersService (Singleton), который внедряет OtherService (Запрос), то и UsersController, и UsersService автоматически становятся областью запроса.

Использование

Либо добавьте егодля @Injectable() декоратора:

@Injectable({ scope: Scope.REQUEST })
export class UsersService {}

Или установите его для пользовательских провайдеров в определении вашего модуля:

{
  provide: 'CACHE_MANAGER',
  useClass: CacheManager,
  scope: Scope.TRANSIENT,
}

Устаревший ответ

Как вы можетесм. в этом выпуске , nestjs пока не предлагает встроенного решения для провайдеров, ограниченных запросами.Но это может произойти в ближайшем будущем:

Как только функция асинхронных перехватчиков (она все еще экспериментальна в узле 10) станет стабильной, мы подумаем о предоставлении встроенного решения для запроса.экземпляры с областью действия.

0 голосов
/ 08 декабря 2018

Я боролся с подобной проблемой, и один из способов добиться этого - использовать модуль node-request-context в качестве глобального регистра запроса, который предоставит вам контекст запроса.Таким образом, у вас не будет отдельных экземпляров службы, но вы можете попросить этот статический регистр предоставить вам запрос конкретного экземпляра / соединения.

https://github.com/guyguyon/node-request-context

Создать простой вспомогательный контекст:

import { createNamespace, getNamespace } from 'node-request-context';
import * as uuid from 'uuid';

export class RequestContext {

    public static readonly NAMESPACE = 'some-namespace';
    public readonly id = uuid.v4();

    constructor(public readonly conn: Connection) { }

    static create(conn: Connection, next: Function) {
        const context = new RequestContext(conn);
        const namespace = getNamespace(RequestContext.NAMESPACE) || createNamespace(RequestContext.NAMESPACE);

        namespace.run(() => {
            namespace.set(RequestContext.name, context);
            next();
        });
    }

    static currentRequestContext(): RequestContext {
        const namespace = getNamespace(RequestContext.NAMESPACE);
        return namespace ? namespace.get(RequestContext.name) : null;
    }

    static getConnection(): Connection {
        const context = RequestContext.currentRequestContext();
        return context ? context.conn : null;
    }

}

Параметр экземпляра conn - это ваше соединение, не стесняйтесь помещать туда другие специфичные для запроса зависимости.Также id существует только для отладки, нет реальной необходимости использовать uuid модуль, как я.

Создать промежуточную оболочку (это позволяет вам использовать DI здесь):

@Injectable()
export class ContextMiddleware implements NestMiddleware {

  constructor(private readonly connectionManager: ...) { }

  resolve(...args: any[]): MiddlewareFunction {
    return (req, res, next) => {
      // create the request specific connection here, probably based on some auth header...
      RequestContext.create(this.connectionManager.createConnection(), next);
    };
  }

}

Затем зарегистрируйте новое промежуточное ПО в своем приложении Nest:

const app = await NestFactory.create(AppModule, {});
app.use(app.get(RequestLoggerMiddleware).resolve());

И, наконец, часть прибыли - получите конкретное соединение для запроса в любом месте вашего приложения:

const conn = RequestContext.getConnection();
...