You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS使用Bull队列时无法获取登录用户认证数据问题

解决Bull队列中无法获取登录用户认证数据的问题

问题核心原因

Bull队列的任务是异步后台执行的,和触发它的HTTP请求不在同一个上下文环境中。常规API请求时,用户认证数据(比如登录用户ID)绑定在当前请求周期的上下文里,但队列任务执行时原请求已结束,上下文被销毁,自然拿不到用户数据。

解决方案

1. 直接传递用户ID到队列任务(最稳妥,无需额外依赖)

在将任务加入队列时,把当前登录用户的ID作为任务参数一起传递,在队列处理器中接收后,再传给数据保存逻辑。

修改 shipments.service.ts 的任务添加逻辑

假设你通过装饰器(比如@CurrentUser)能在API方法中拿到当前登录用户:

// shipments.service.ts
async createShipment(data: ShipmentDto, @CurrentUser() user: User) {
  // 将用户ID作为任务参数传入队列
  await this.bullQueue.add('create-shipment', {
    shipmentData: data,
    creatorId: user.id
  });
}

在队列处理器中接收用户ID并传递给保存方法

如果没有队列处理器文件,新建shipments.processor.ts:

// shipments.processor.ts
import { Processor, Process, Job } from '@nestjs/bull';
import { ShipmentsService } from './shipments.service';

@Processor('shipments') // 和addJob时的队列名称一致
export class ShipmentsProcessor {
  constructor(private readonly shipmentsService: ShipmentsService) {}

  @Process('create-shipment') // 和addJob时的任务名称一致
  async handleCreateShipment(job: Job<{ shipmentData: ShipmentDto; creatorId: string }>) {
    const { shipmentData, creatorId } = job.data;
    // 调用保存方法时传入用户ID
    await this.shipmentsService.saveShipmentWithCreator(shipmentData, creatorId);
  }
}

修改实体保存逻辑,接受外部传入的创建者ID

调整base.entity.ts,不要在实体内部尝试获取用户(队列中无上下文),改为从外部接收创建者ID:

// base.entity.ts
import { Column, CreateDateColumn } from 'typeorm';
import { Repository } from 'typeorm';

export abstract class BaseEntity {
  @Column({ nullable: false })
  createdBy: string;

  @CreateDateColumn()
  createdAt: Date;

  // 传入创建者ID后再执行保存
  async saveWithCreator<T extends BaseEntity>(
    creatorId: string,
    repository: Repository<T>
  ): Promise<T> {
    this.createdBy = creatorId;
    return repository.save(this as unknown as T);
  }
}

然后在shipments.service.ts中实现对应的保存方法:

// shipments.service.ts
async saveShipmentWithCreator(data: ShipmentDto, creatorId: string) {
  const shipment = this.shipmentRepository.create(data);
  // 调用BaseEntity的保存方法,传入创建者ID
  return shipment.saveWithCreator(creatorId, this.shipmentRepository);
}

2. 传递完整请求上下文(复杂场景可选)

如果需要传递更多用户上下文信息(而非仅ID),可以用Node.js的AsyncLocalStorage(NestJS原生支持)传递上下文快照,但仅适用于单进程队列(分布式队列不适用)。

在app.module.ts中配置AsyncLocalStorage

// app.module.ts
import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common';
import { AsyncLocalStorage } from 'async_hooks';
import { ShipmentsModule } from './shipments/shipments.module';

@Module({
  imports: [ShipmentsModule],
  providers: [
    {
      provide: 'ASYNC_LOCAL_STORAGE',
      useValue: new AsyncLocalStorage<Map<string, any>>(),
    },
  ],
})
export class AppModule implements NestModule {
  constructor(@Inject('ASYNC_LOCAL_STORAGE') private readonly als: AsyncLocalStorage<Map<string, any>>) {}

  configure(consumer: MiddlewareConsumer) {
    consumer.apply((req, res, next) => {
      // 请求开始时将用户信息存入ALS
      this.als.run(new Map(), () => {
        this.als.getStore().set('user', req.user); // 假设req.user是登录用户对象
        next();
      });
    }).forRoutes('*');
  }
}

在shipments.service.ts中传递上下文快照

// shipments.service.ts
constructor(
  @Inject('ASYNC_LOCAL_STORAGE') private readonly als: AsyncLocalStorage<Map<string, any>>,
  @InjectQueue('shipments') private readonly bullQueue: Queue,
) {}

async createShipment(data: ShipmentDto) {
  // 获取当前上下文快照
  const contextSnapshot = this.als.getStore();
  await this.bullQueue.add('create-shipment', {
    shipmentData: data,
    contextSnapshot
  });
}

在队列处理器中恢复上下文并使用

// shipments.processor.ts
@Process('create-shipment')
async handleCreateShipment(job: Job<{ shipmentData: ShipmentDto; contextSnapshot: Map<string, any> }>) {
  const { shipmentData, contextSnapshot } = job.data;
  // 恢复上下文后执行保存逻辑
  await this.als.run(contextSnapshot, async () => {
    const user = this.als.getStore().get('user');
    await this.shipmentsService.saveShipmentWithCreator(shipmentData, user.id);
  });
}

关键提醒

  • 不要在Entity内部直接获取用户数据:Entity是数据库模型,职责是映射数据,不应依赖请求上下文或处理业务逻辑。
  • 分布式队列场景下,只能用传递用户ID的方式:上下文快照无法跨进程/机器传递,直接传ID是最可靠的方案。

内容的提问来源于stack exchange,提问作者anshulCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:27:41