在全局(单例)服务中使用特定于请求的上下文
Posted
技术标签:
【中文标题】在全局(单例)服务中使用特定于请求的上下文【英文标题】:Use request-specific context inside a global (singleton) service 【发布时间】:2020-01-06 11:13:47 【问题描述】:我希望能够记录(如console.log
)每个正在执行的 SQL 查询的登录用户。我正在使用 Nest.js 和 TypeORM(它是 Nest.js 的包装器)。我不知道如何将特定于请求的数据注入到全局(单例)提供程序中。
我正在使用 Nest.js v6.6.3 和 @nestjs/typeorm
v6.1.3。
// current-user.service.ts
@Injectable( scope: Scope.REQUEST )
export class CurrentUserService
get currentUser(): string | null
if (!this.request || !this.request.user)
return null;
return this.request.user.email;
constructor(@Optional() @Inject(REQUEST) private request: Request)
// logger.service.ts
@Injectable()
export class LoggerService extends Logger
constructor(private readonly moduleRef: ModuleRef)
super();
log(message: any, context?: string)
super.log(this.formatMessage(message), context);
private formatMessage(message: any)
// ** This is the problematic code **
const currentUserService = this.moduleRef.get(CurrentUserService,
strict: false,
);
return `[$currentUserService.currentUser]: $message`;
// typeorm-logger.service.ts
@Injectable()
export class TypeormLogger implements Logger
// Logger is imported from `typeorm`
constructor(private logger: LoggerService)
logQuery(query: string)
// there are more params, don't matter for the sake of the argument
this.logger.log(query);
// logger.module.ts
@Module(
providers: [LoggerService, TypeormLogger],
exports: [LoggerService, TypeormLogger],
)
export class LoggerModule
// app.module.ts
@Module(
imports: [
TypeOrmModule.ForRootAsync(
imports: [LoggerModule],
inject: [TypeormLogger],
useFactory: (typeormLogger: TypeormLogger) =>
return
type: 'mysql',
logger: typeormLogger,
keepConnectionAlive: false,
...
;
,
),
],
)
export class AppModule
似乎使用moduleRef.get()
不能进行交叉Module
解析,所以我尝试使用moduleRef.resolve()
代替,但我仍然得到CurrentUserService
和request === undefined
。此外,resolve()
返回一个 Promise
,这对于日志记录之类的东西并不理想。
以上是一个特定的用例,但可以概括 - 如果您的代码不是直接从控制器调用的,则不能注入像经过身份验证的用户或请求 id 这样的瞬态数据(两者都对日志记录很有用)。这看起来很奇怪,尤其是 Nest.js 严重依赖 IoC。
【问题讨论】:
这个运气好吗?我在同一条船上。 【参考方案1】:我最终解决了 Nest.js,到目前为止它似乎运行良好。请注意,我们在内部应用程序中使用它,所以我们的并发用户数很少,所以 YMMV。
该解决方案基于asyncctx
包,正如here 建议的那样。你可以找到完整的解决方案here。
【讨论】:
@AgentLiquid - 见上文以上是关于在全局(单例)服务中使用特定于请求的上下文的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Oracle EBS 中基于表的值集中使用描述性弹性域上下文