我正尝试在Nest/TypeORM上构建一个SAAS产品,我需要通过子域配置/更改数据库连接。
customer1.domain.com => connect to customer1 database
customer2.domain.com => connect to customer2 database
x.domain.com => connect to x database
我该怎么做呢?使用拦截器还是请求上下文(或Zone.js)?
我不知道该怎么开始。有人已经开始了吗?
WIP:我当前正在做的事情:
1.添加所有连接设置到ormconfig文件
1.在所有路由上创建中间件以将子域注入res.locals
(示例名)并创建/警告typeorm连接
import { Injectable, NestMiddleware, MiddlewareFunction } from '@nestjs/common';
import { getConnection, createConnection } from "typeorm";
@Injectable()
export class DatabaseMiddleware implements NestMiddleware {
resolve(): MiddlewareFunction {
return async (req, res, next) => {
const instance = req.headers.host.split('.')[0]
res.locals.instance = instance
try {
getConnection(instance)
} catch (error) {
await createConnection(instance)
}
next();
};
}
}
1.在控制器中:从@Response获取示例名称并将其传递给我的服务
@Controller('/catalog/categories')
export class CategoryController {
constructor(private categoryService: CategoryService) {}
@Get()
async getList(@Query() query: SearchCategoryDto, @Response() response): Promise<Category[]> {
return response.send(
await this.categoryService.findAll(response.locals.instance, query)
)
}
1.使用中:获取给定示例的TypeORM管理器并通过存储库查询数据库
@Injectable()
export class CategoryService {
// constructor(
// @InjectRepository(Category) private readonly categoryRepository: Repository<Category>
// ) {}
async getRepository(instance: string): Promise<Repository<Category>> {
return (await getManager(instance)).getRepository(Category)
}
async findAll(instance: string, dto: SearchCategoryDto): Promise<Category[]> {
let queryBuilder = (await this.getRepository(instance)).createQueryBuilder('category')
if (dto.name) {
queryBuilder.andWhere("category.name like :name", { name: `%${dto.name}%` })
}
return await queryBuilder.getMany();
}
它似乎工作,但我不确定几乎所有的东西:
- 连接池(我可以在ConnectionManager中创建多少个连接?)
- 将子域传递到response. locals...不良做法?
- 可读性/理解力/添加大量额外代码...
- 副作用:我害怕在多个子域之间共享连接
- 副作用:性能
这不是一个愉快的处理响应。发送()+承诺+等待(s)+传递子域无处不在...
有没有办法让子域直接进入我的服务?
是否有方法直接将正确的子域连接/存储库获取到我的服务中,并将其注入到我的控制器中?
5条答案
按热度按时间f0brbegy1#
我想到了另一个解决办法。
我创建了一个中间件来获取特定租户的连接:
我把它添加到主.ts:
要访问连接,您可以通过以下方式扩展任何服务:
它仍然是一个草稿,但是有了这个解决方案,您可以在运行时为每个租户添加、删除和编辑连接。
yacmzcpb2#
我从yoh的解决方案中得到了灵感,但是我根据NestJS的新特性对它做了一些调整,结果是代码更少了。
1)我创建了
DatabaseMiddleware
2)在main中,ts对每个路由都使用它
3)服务中检索连接
xn1cxnb43#
应使用范围为
REQUEST
的自定义提供程序。租赁提供商
服务等级
然后在你的服务上,你可以得到这样的连接:
您可以在以下多租户文章中获得更多信息:https://tech.canyonlegal.com/multitenancy-with-nestjs-typeorm-postgres
qcuzuvrc4#
最好的方法是使用一个动态模块,就像你对request scope所做的那样,来获取
ORM
连接,并使其特定于连接。一个非常简单的示例如下:在这个示例中,我使用了mysql 2-nestjs模块,但是您可以使用自己
ORM
来创建tenancyFactory
您是否在以下lingx 1 e0f1x中的工作溶液中找到此示例
xqkwcwgp5#
我为nest-mongodb编写了一个解决这个问题的实现,请查看它,它可能会有帮助。
类似问题https://stackoverflow.com/a/57842819/7377682