cube.js 0.30.30 之后自定义driver 开发的一些问题说明
driverFactory 的变动
- driver 解析
public async resolveDriver(
context: DriverContext,
options?: OrchestratorInitedOptions,
): Promise<BaseDriver> {
if (!this.driversStorage.has(context.dataSource)) {
const val = await this.options.driverFactory(context);
if (val instanceof BaseDriver) {
this.driversStorage.set(context.dataSource, val);
} else {
const { type,
const opts = Object.keys(rest).length
? rest
: {
maxPoolSize: await CubejsServerCore.getDriverMaxPool(context, options),
};
this.driversStorage.set(
context.dataSource,
CubejsServerCore.createDriver(type, opts),
);
}
}
return this.driversStorage.get(context.dataSource);
}
- 获取driverFactory
private getDriverFactory(opts: CreateOptions): DriverFactoryAsyncFn {
const { dbType, driverFactory } = opts;
this.decoratedType = !dbType;
this.decoratedFactory = !driverFactory;
return async (ctx: DriverContext) => {
if (!driverFactory) {
if (!this.driverFactoryType) {
this.driverFactoryType = 'DriverConfig';
} else if (this.driverFactoryType !== 'DriverConfig') {
throw new Error(
'CreateOptions.driverFactory function must return either ' +
'BaseDriver or DriverConfig.'
);
}
// TODO (buntarb): wrapping this call with assertDriverFactoryResult
// change assertions sequince and cause a fail of few tests. Review it.
return this.defaultDriverFactory(ctx);
} else {
// 对于自定义driver 会到此处,也是问题产生的原因
return this.assertDriverFactoryResult(
await driverFactory(ctx),
);
}
};
}
- ts 类型定义
export type DriverFactoryFn = (context: DriverContext) =>
Promise<BaseDriver | DriverConfig> | BaseDriver | DriverConfig;
- assertDriverFactoryResult 方法处理
private assertDriverFactoryResult(
val: DriverConfig | BaseDriver,
) {
// 包含了对于BaseDriver 以及DriverConfig
if (val instanceof BaseDriver) {
// TODO (buntarb): these assertions should be restored after dbType
// deprecation period will be passed.
//
// if (this.decoratedType) {
// throw new Error(
// 'CreateOptions.dbType is required if CreateOptions.driverFactory ' +
// 'returns driver instance'
// );
// }
// this.core.logger(
// 'Cube.js CreateOptions.driverFactory Property Deprecation',
// {
// warning: (
// // TODO (buntarb): add https://github.com/cube-js/cube.js/blob/master/DEPRECATION.md#driverFactory
// // link once it will be created.
// 'CreateOptions.driverFactory should return DriverConfig object instead of driver instance, please migrate.'
// ),
// },
// );
if (!this.driverFactoryType) {
this.driverFactoryType = 'BaseDriver';
} else if (this.driverFactoryType !== 'BaseDriver') {
throw new Error(
'CreateOptions.driverFactory function must return either ' +
'BaseDriver or DriverConfig.'
);
}
return <BaseDriver>val;
// 此处的类型判定比较重要了,如果我们自定义的driver 包含了type 就可以很好的解决此类问题
} else if (
val && val.type && typeof val.type === 'string'
) {
if (!this.driverFactoryType) {
this.driverFactoryType = 'DriverConfig';
} else if (this.driverFactoryType !== 'DriverConfig') {
throw new Error(
'CreateOptions.driverFactory function must return either ' +
'BaseDriver or DriverConfig.'
);
}
return <DriverConfig>val;
} else {
throw new Error(
'Unexpected CreateOptions.driverFactory result value. Must be either ' +
`DriverConfig or driver instance: <${
typeof val
}>${
JSON.stringify(val, undefined, 2)
}`
);
}
}
- driver 查找以及创建
export const lookupDriverClass = (dbType): Constructor<BaseDriver> & {
dialectClass?: () => any;
getDefaultConcurrency?: () => number;
} => {
// eslint-disable-next-line global-require,import/no-dynamic-require
const module = require(
driverDependencies(dbType || process.env.CUBEJS_DB_TYPE)
);
// 注意此处的处理
if (module.default) {
return module.default;
}
return module;
};
export const createDriver = (
type: DatabaseType,
options?: DriverOptions,
): BaseDriver => new (lookupDriverClass(type))(options);
自定义driver 的变动
class DremioDriver extends BaseDriver {
static dialectClass() {
return DremioQuery;
}
/**
* Returns default concurrency value.
*/
static getDefaultConcurrency() {
return 2;
}
constructor(config = {}) {
super();
// for cube.js latest version, if we write one custome driver should add this
this.type="mydremio"; // 此处需要添加,解决自定义driver 的问题
this.config = {
host: config.host || process.env.CUBEJS_DB_HOST || 'localhost',
port: config.port || process.env.CUBEJS_DB_PORT || 9047,
user: config.user || process.env.CUBEJS_DB_USER,
password: config.password || process.env.CUBEJS_DB_PASS,
database: config.database || process.env.CUBEJS_DB_NAME,
ssl: config.ssl || process.env.CUBEJS_DB_SSL,
pollTimeout: (config.pollTimeout || getEnv('dbPollTimeout') || getEnv('dbQueryTimeout')) * 1000,
pollMaxInterval: (config.pollMaxInterval || getEnv('dbPollMaxInterval')) * 1000,
};
const protocol = (this.config.ssl === true || this.config.ssl === 'true') ? 'https' : 'http';
this.config.url = `${protocol}://${this.config.host}:${this.config.port}`;
}
说明
以上是一个简单的变动说明,以及自定义driver 开发的兼容处理
参考资料
packages/cubejs-server-core/src/core/DriverResolvers.ts
packages/cubejs-server-core/src/core/OptsHandler.ts