设置信息
在解决实际问题之前,让我向您解释一下架构设置。所以我们有一个带有主从配置的Postgres集群。在这个集群中,我们使用了同步复制策略和sychronous_commit作为remote_apply。
问题陈述
我们将 TypeOrm 与 NestJs 结合使用(不详细介绍模块如何实例化以及连接如何发生,请考虑它正在发生,并且我们能够通过 TypeOrm 创建的连接获取数据)。
我们已经公开了某些函数来通过 TypeOrm API 与表对话。
问题是,当我们在任何表上执行选择查询时,它会自动尝试从 Postgres 集群的 SLAVE 获取它。
查询
是否有任何 Typeorm api 选项可用,通过它我们可以告诉 TypeOrm,对于特定调用请不要转到 Slave,而是转到 master 来执行。
今天我们使用的是这样的东西:
/**
PLEASE CONSIDER ALL IMPORTS AND CONFIGS WORKING PERFECTLY FINE FOR NESTJS
*/
export class SomeClassName {
constructor(@InjectRepository(ENTITYNAME) private readonly entityRepository: Repository<Entity>) {}
/**
*
* @description this function finds the record from the db and return it
* @param id the record that needs to be returned
*/
async findSomething(id: string): Promise<Entity> {
/**
* This call is going to PG Cluster Slave since its a SELECT call (behind the scenes).
* What we want, is for this call, we will pass any FLAG or ANY config,
* that forces TYPEORM to get this specific data from MASTER
*/
return this.entityRepository.findOne({ job_id: id });
}
}
如果存储库模式无法实现,是否有其他方法可以告诉 Typeorm 从 Master 获取数据?
请发表一些看法。快乐编码:)
解决方案是注入 EntityManager 并创建指定数据库的查询运行器
const queryRunner = this.entityManager.connection.createQueryRunner('master')
然后使用
queryRunner.manager(Entity, query)
理想的解决方案是为数据库配置 typeorm MASTER 和 SLAVE 服务器 像这样的东西应该对你有用
所有插入都将通过主设备进行,读取将在从设备之间均匀重定向
function getOptions(): DataSourceOptions {
const type = 'postgres';
const logging = process.env.DB_LOGGING === 'true';
const synchronize = process.env.DB_SYNCHRONIZE === 'true';
const entities = [path.resolve(__dirname, 'src', '**', 'entities/*{index.ts,.entity.ts,.entity.js}')];
const migrations = [path.resolve(__dirname, 'src', 'database', 'migrations/*{.ts,.js}')];
const migrationsRun = process.env.DB_MIGRATIONS_RUN === 'true';
if (process.env.DB_REPLICATION === 'true') {
const master = {
host: process.env.DB_HOST_MASTER,
port: Number.parseInt(process.env.DB_PORT_MASTER ?? '', 10),
username: process.env.DB_USERNAME_MASTER,
password: process.env.DB_PASSWORD_MASTER,
database: process.env.DB_NAME_MASTER
};
const slaves: PostgresConnectionCredentialsOptions[] = [];
for (let i = 0; ; i++) {
if (process.env[`DB_HOST_SLAVE_${i}`]) {
slaves.push({
host: process.env[`DB_HOST_SLAVE_${i}`],
port: Number.parseInt(process.env[`DB_PORT_SLAVE_${i}`] ?? '', 10),
username: process.env[`DB_USERNAME_SLAVE_${i}`],
password: process.env[`DB_PASSWORD_SLAVE_${i}`],
database: process.env[`DB_NAME_SLAVE_${i}`]
});
} else {
break;
}
}
return {
type,
replication: {
master,
slaves
},
logging,
synchronize,
entities,
migrations,
migrationsRun
};
} else {
return {
type,
host: process.env.DB_HOST,
port: Number.parseInt(process.env.DB_PORT ?? '', 10),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
logging,
synchronize,
entities,
migrations,
migrationsRun
};
}
}