@zenweb/tenant
Version:
Zenweb Tenant module
67 lines (66 loc) • 2.18 kB
JavaScript
import { $getContext } from '@zenweb/core';
import modMySQL from '@zenweb/mysql';
export * from './types.js';
/**
* 当前上下文取得的租户信息
*/
const TENANT = Symbol.for('zenweb@tenant');
/**
* 生成租户数据库配置信息
*/
export function makeTenantMySQLOption(option) {
// 重组配置
const pools = {};
// 对应的服务器是否有从库
const haveSlaves = {};
for (const [server, poolConfig] of Object.entries(option.pools)) {
pools[`${server}_MASTER`] = poolConfig.MASTER;
if (poolConfig.SLAVES && poolConfig.SLAVES.length > 0) {
haveSlaves[server] = true;
let i = 1;
for (const slave of poolConfig.SLAVES) {
pools[`${server}_SLAVE${i}`] = slave;
i++;
}
}
else {
haveSlaves[server] = false;
}
}
return {
cluster: option.cluster,
pools,
bindQuery: option.bindQuery,
// 所属数据库服务器切换
async getPoolConnectionBefore(opt) {
const ctx = $getContext();
if (!ctx[TENANT]) {
ctx[TENANT] = await option.tenantGetter(ctx);
}
return {
// 将原有选择规则增加前缀
// 判断是否有从库,如果没有强制走主库
pattern: ctx[TENANT].server + '_' + ((haveSlaves[ctx[TENANT].server] && opt?.pattern) || 'MASTER'),
selector: opt?.selector,
};
},
// 所属数据库切换 (复用连接池)
getPoolConnectionAfter(conn) {
return new Promise((resolve, reject) => {
const ctx = $getContext();
conn.query('USE `' + ctx[TENANT].database + '`', err => {
if (err)
reject(err);
else
resolve();
});
});
},
};
}
export default function setup(option) {
return function tenant(setup) {
setup.debug('option: %o', option);
setup.core.setup(modMySQL(makeTenantMySQLOption(option)));
};
}