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

如何在NestJS中重新初始化EdgeDB数据库提供者以应用更新配置?

解决NestJS+EdgeDB全局变量不生效的问题

核心问题分析

  1. EdgeDB客户端不可变性:withGlobals()返回新的客户端实例,而非修改原实例,若未替换服务中的client引用,后续查询仍使用旧实例。
  2. 单例作用域冲突:NestJS默认单例服务全局共享,存储请求级别的current_user_id会导致并发请求互相覆盖。
  3. 异步调用未等待:若调用setGlobals时未加await,后续操作会在实例更新完成前执行,导致全局变量未生效。

解决方案

1. 修改EdgeDBService为请求作用域

将服务改为请求级作用域,每个请求生成独立的服务实例,彻底隔离请求上下文:

import { Injectable, Scope, OnModuleInit } from '@nestjs/common';
import * as edgedb from 'edgedb';
import type { EdgeQLTypes } from 'edgedb';

@Injectable({ scope: Scope.REQUEST }) // 关键:设置请求作用域
export class EdgeDBService implements OnModuleInit {
  client: edgedb.Client;

  constructor() {
    this.client = edgedb.createClient();
  }

  async onModuleInit() {
    await this.client.ensureConnected();
  }

  public async setGlobals(globals: { current_user_id: string }) {
    // 替换为带全局变量的新客户端实例
    this.client = this.client.withGlobals(globals);
    console.log(await this.client.query(`select global current_user_id;`));
  }

  public async query<Expr extends EdgeQLTypes.Expression>(expression: Expr): Promise<EdgeQLTypes.$infer<Expr>> {
    return expression.run(this.client);
  }
}

2. 确保异步调用等待完成

调用setGlobals时必须加await,保证客户端实例更新后再执行查询:

// 示例控制器代码
import { Controller, Get, Req } from '@nestjs/common';
import { EdgeDBService } from './edgedb.service';
import { PetsService } from './pets.service';

@Controller('pets')
export class PetsController {
  constructor(
    private readonly edgedb: EdgeDBService,
    private readonly petsService: PetsService
  ) {}

  @Get()
  async getPets(@Req() req) {
    // 等待全局变量设置完成
    await this.edgedb.setGlobals({ current_user_id: req.user.id });
    return this.petsService.getPets();
  }
}

3. 优化PetsService的查询逻辑

统一使用EdgeDBService提供的query方法,避免直接访问client属性,确保使用最新的客户端实例:

import { Injectable } from '@nestjs/common';
import * as e from '../dbschema/edgeql-js';
import { EdgeDBService } from './edgedb.service';

@Injectable()
export class PetsService {
  constructor(private readonly edgedb: EdgeDBService) {}

  async getPets() {
    // 使用query方法获取全局变量,确保用最新实例
    const currentUserId = await this.edgedb.query(e.select(e.global.current_user_id));
    console.log(currentUserId);

    return this.edgedb.query(
      e.select(e.Pets, (item) => ({
        ...e.Pets['*'],
      }))
    );
  }
}

关键说明

  • 请求作用域的服务会为每个HTTP请求创建新实例,完全避免并发请求间的全局变量冲突。
  • EdgeDB的withGlobals()是不可变操作,必须替换服务中的client引用才能让后续查询生效。
  • 所有异步操作必须等待完成,否则会出现实例未更新的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:44:56