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, ...rest } = val;
        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,
      ...config,
      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

posted on 2022-07-17 23:29  荣锋亮  阅读(98)  评论(0编辑  收藏  举报

导航