@mwcp/kmore
Version:
midway component for knex, supports declarative transaction and OpenTelemetry
306 lines • 12.9 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
/* eslint-disable max-lines-per-function */
import assert from 'node:assert';
import { App, ApplicationContext, DataSourceManager, Init, Inject, Logger as _Logger, Singleton, } from '@midwayjs/core';
import { SpanKind, Trace, TraceInit } from '@mwcp/otel';
import { MConfig, getWebContext } from '@mwcp/share';
// eslint-disable-next-line import/no-extraneous-dependencies
import { context } from '@opentelemetry/api';
import { KmoreFactory, getCurrentTime, } from 'kmore';
import { DbEvent } from './db-event.js';
import { DbHook } from './db-hook/index.db-hook.js';
import { eventNeedTrace, genCommonAttr } from './trace.helper.js';
import { TrxStatusService } from './trx-status.service.js';
import { ConfigKey, KmoreAttrNames } from './types.js';
let DbManager = class DbManager extends DataSourceManager {
sourceConfig;
app;
applicationContext;
logger;
baseDir;
dbEvent;
dbHook;
trxStatusSvc;
async init() {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!this?.sourceConfig?.dataSource) {
this.logger.info('dataSourceConfig is not defined');
return;
}
await this.initDataSource(this.sourceConfig, '');
}
getDbConfigByDbId(dbId) {
assert(dbId);
const dbConfig = this.sourceConfig.dataSource[dbId];
return dbConfig;
}
getWebContext() {
return getWebContext(this.applicationContext);
}
getWebContextThenApp() {
try {
const webContext = getWebContext(this.applicationContext);
assert(webContext, 'getActiveContext() webContext should not be null, maybe this calling is not in a request context');
return webContext;
}
catch (ex) {
console.warn('getWebContextThenApp() failed', ex);
return this.app;
}
}
getName() {
return 'dbManager';
}
// #region checkConnected
async checkConnected(dataSource) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!dataSource) {
return false;
}
const { dbh, config } = dataSource;
try {
const time = await getCurrentTime(dbh, config.client);
return !!time;
}
catch (ex) {
this.logger.error('[KmoreDbSourceManager]: checkConnected(). error ignored', ex);
}
return false;
}
// #region createDataSource
/**
* 创建单个实例
*/
async createDataSource(config, dataSourceName) {
const inst = await this._createDataSource(config, dataSourceName);
assert(inst, `createDataSource() failed: ${dataSourceName}`);
this.dbHook.createProxy(inst);
return inst;
}
// #region getDataSource
getDataSource(dataSourceName) {
const db = super.getDataSource(dataSourceName);
assert(db, `[${ConfigKey.componentName}] getDataSource() db source empty: "${dataSourceName}"`);
assert(db.dbId === dataSourceName, `[${ConfigKey.componentName}] getDataSource() db source id not match: "${dataSourceName}"`);
return db;
}
// #region destroyDataSource
async destroyDataSource(dataSource) {
if (await this.checkConnected(dataSource)) {
try {
await dataSource.destroy();
this.dataSource.delete(dataSource.dbId);
this.trxStatusSvc.unregisterDbInstance(dataSource.dbId);
}
catch (ex) {
this.logger.error(`Destroy knex connection failed with identifier: "${dataSource.instanceId.toString()}" :
\n${ex.message}`);
}
}
}
/**
* 创建单个实例
*/
async _createDataSource(config, dataSourceName) {
const globalEventCbs = {
start: (event, kmore) => {
if (kmore.enableTrace) {
let activeTraceCtx;
const traceScope = this.dbEvent.retrieveTraceScope(kmore, event.kmoreQueryId, event.queryBuilder);
const activeRoot = this.trxStatusSvc.getTraceContextByScope(traceScope);
if (activeRoot) {
activeTraceCtx = activeRoot;
}
else {
const trx = kmore.getTrxByQueryId(event.kmoreQueryId);
activeTraceCtx = trx ? kmore.trx2TraceContextMap.get(trx) : void 0;
}
if (!activeTraceCtx) {
activeTraceCtx = context.active();
}
context.with(activeTraceCtx, () => {
this.dbEvent.onStart({ dataSourceName, dbConfig: config, event, kmore });
});
return;
}
this.dbEvent.onStart({ dataSourceName, dbConfig: config, event, kmore });
},
query: (event, kmore) => {
if (kmore.enableTrace) {
let activeTraceCtx = this.trxStatusSvc.getTraceContextByScope(event.kmoreQueryId);
if (!activeTraceCtx) {
const traceScope = this.dbEvent.retrieveTraceScope(kmore, event.kmoreQueryId, event.queryBuilder);
const active = this.trxStatusSvc.getTraceContextByScope(traceScope);
if (active) {
activeTraceCtx = active;
}
else {
const trx = kmore.getTrxByQueryId(event.kmoreQueryId);
activeTraceCtx = trx ? kmore.trx2TraceContextMap.get(trx) : void 0;
}
}
context.with(activeTraceCtx ?? context.active(), () => {
this.dbEvent.onQuery({ dataSourceName, dbConfig: config, event, kmore });
});
return;
}
this.dbEvent.onQuery({ dataSourceName, dbConfig: config, event, kmore });
},
queryResponse: (event, kmore) => {
if (kmore.enableTrace) {
let activeTraceCtx = this.trxStatusSvc.getTraceContextByScope(event.kmoreQueryId);
if (!activeTraceCtx) {
const traceScope = this.dbEvent.retrieveTraceScope(kmore, event.kmoreQueryId, event.queryBuilder);
const active = this.trxStatusSvc.getTraceContextByScope(traceScope);
if (active) {
activeTraceCtx = active;
}
else {
const trx = kmore.getTrxByQueryId(event.kmoreQueryId);
activeTraceCtx = trx ? kmore.trx2TraceContextMap.get(trx) : void 0;
}
}
context.with(activeTraceCtx ?? context.active(), () => {
this.dbEvent.onResp({ dataSourceName, dbConfig: config, event, kmore });
});
return;
}
this.dbEvent.onResp({ dataSourceName, dbConfig: config, event, kmore });
},
queryError: (event, kmore) => {
if (kmore.enableTrace) {
let activeTraceCtx = this.trxStatusSvc.getTraceContextByScope(event.kmoreQueryId);
if (!activeTraceCtx) {
const traceScope = this.dbEvent.retrieveTraceScope(kmore, event.kmoreQueryId, event.queryBuilder);
const active = this.trxStatusSvc.getTraceContextByScope(traceScope);
if (active) {
activeTraceCtx = active;
}
else {
const trx = kmore.getTrxByQueryId(event.kmoreQueryId);
activeTraceCtx = trx ? kmore.trx2TraceContextMap.get(trx) : void 0;
}
}
return context.with(activeTraceCtx ?? context.active(), () => {
return this.dbEvent.onError({ dataSourceName, dbConfig: config, event, kmore });
});
}
return this.dbEvent.onError({ dataSourceName, dbConfig: config, event, kmore });
},
};
const opts = {
dbId: dataSourceName,
...config,
eventCallbacks: globalEventCbs,
};
const inst = KmoreFactory(opts);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!this.sourceConfig.dataSource[dataSourceName]) {
this.sourceConfig.dataSource[dataSourceName] = config;
}
return inst;
}
};
__decorate([
MConfig(ConfigKey.config),
__metadata("design:type", Object)
], DbManager.prototype, "sourceConfig", void 0);
__decorate([
App(),
__metadata("design:type", Object)
], DbManager.prototype, "app", void 0);
__decorate([
ApplicationContext(),
__metadata("design:type", Object)
], DbManager.prototype, "applicationContext", void 0);
__decorate([
_Logger(),
__metadata("design:type", Object)
], DbManager.prototype, "logger", void 0);
__decorate([
Inject(),
__metadata("design:type", String)
], DbManager.prototype, "baseDir", void 0);
__decorate([
Inject(),
__metadata("design:type", DbEvent)
], DbManager.prototype, "dbEvent", void 0);
__decorate([
Inject(),
__metadata("design:type", DbHook)
], DbManager.prototype, "dbHook", void 0);
__decorate([
Inject(),
__metadata("design:type", TrxStatusService)
], DbManager.prototype, "trxStatusSvc", void 0);
__decorate([
TraceInit(`INIT ${ConfigKey.namespace}.DbSourceManager.init()`),
Init(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], DbManager.prototype, "init", null);
__decorate([
Trace({
spanName: () => 'DbManager getDataSource',
startActiveSpan: false,
kind: SpanKind.INTERNAL,
before([dataSourceName]) {
const dbConfig = this.getDbConfigByDbId(dataSourceName);
if (dbConfig && !eventNeedTrace(KmoreAttrNames.getDataSourceStart, dbConfig)) {
return;
}
const attrs = {
dbId: dataSourceName,
};
const events = genCommonAttr(KmoreAttrNames.getDataSourceStart);
return { attrs, events };
},
after([dataSourceName]) {
const dbConfig = this.getDbConfigByDbId(dataSourceName);
if (dbConfig && !eventNeedTrace(KmoreAttrNames.getDataSourceStart, dbConfig)) {
return;
}
const events = genCommonAttr(KmoreAttrNames.getDataSourceEnd);
return { events };
},
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Function)
], DbManager.prototype, "getDataSource", null);
__decorate([
TraceInit({
spanName: ([, dataSourceName]) => `INIT ${ConfigKey.namespace}.DbSourceManager._createDataSource():${dataSourceName}`,
before: (args) => {
if (!args[0].traceInitConnection) {
return;
}
const config = { ...args[0] };
delete config.dict;
delete config.eventCallbacks;
const events = {
event: 'createDataSource.before',
config: JSON.stringify(config),
dataSourceName: args[1],
};
return { events };
},
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object, String]),
__metadata("design:returntype", Promise)
], DbManager.prototype, "_createDataSource", null);
DbManager = __decorate([
Singleton()
], DbManager);
export { DbManager };
//# sourceMappingURL=db-source-manager.js.map