Skip to content

Commit

Permalink
feat(core): allow configuring driverOptions on replica level
Browse files Browse the repository at this point in the history
  • Loading branch information
B4nan committed Apr 9, 2024
1 parent 2c472ab commit 05e81f8
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 13 deletions.
4 changes: 2 additions & 2 deletions packages/core/src/connections/Connection.ts
Expand Up @@ -21,9 +21,9 @@ export abstract class Connection {
this.logger = this.config.getLogger();

if (options) {
this.options = options;
this.options = Utils.copy(options);
} else {
const props = ['dbName', 'clientUrl', 'host', 'port', 'user', 'password', 'multipleStatements', 'pool', 'schema'] as const;
const props = ['dbName', 'clientUrl', 'host', 'port', 'user', 'password', 'multipleStatements', 'pool', 'schema', 'driverOptions'] as const;
this.options = props.reduce((o, i) => {
(o[i] as any) = this.config.get(i);
return o;
Expand Down
30 changes: 24 additions & 6 deletions packages/core/src/drivers/DatabaseDriver.ts
Expand Up @@ -420,14 +420,32 @@ export abstract class DatabaseDriver<C extends Connection> implements IDatabaseD
}

protected createReplicas(cb: (c: ConnectionOptions) => C): C[] {
const replicas = this.config.get('replicas', [])!;
const replicas = this.config.get('replicas', []) as ConnectionOptions[];
const ret: C[] = [];
const props = ['dbName', 'clientUrl', 'host', 'port', 'user', 'password', 'multipleStatements', 'pool', 'name'] as const;
const props = ['dbName', 'clientUrl', 'host', 'port', 'user', 'password', 'multipleStatements', 'pool', 'name', 'driverOptions'] as const;

replicas.forEach((conf: Partial<ConnectionOptions>) => {
props.forEach(prop => (conf[prop] as any) = prop in conf ? conf[prop] : this.config.get(prop));
ret.push(cb(conf as ConnectionOptions));
});
for (const conf of replicas) {
const replicaConfig = Utils.copy(conf) as Dictionary;

for (const prop of props) {
if (conf[prop]) {
continue;
}

// do not copy options that can be inferred from explicitly provided `clientUrl`
if (conf.clientUrl && ['clientUrl', 'host', 'port', 'user', 'password'].includes(prop)) {
continue;
}

if (conf.clientUrl && prop === 'dbName' && new URL(conf.clientUrl).pathname) {
continue;
}

replicaConfig[prop] = this.config.get(prop);
}

ret.push(cb(replicaConfig as ConnectionOptions));
}

return ret;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/utils/Configuration.ts
Expand Up @@ -463,6 +463,7 @@ export interface ConnectionOptions {
collate?: string;
multipleStatements?: boolean; // for mysql driver
pool?: PoolConfig;
driverOptions?: Dictionary;
}

export type MigrationsOptions = {
Expand Down Expand Up @@ -540,7 +541,6 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
filters: Dictionary<{ name?: string } & Omit<FilterDef, 'name'>>;
discovery: MetadataDiscoveryOptions;
driver?: { new(config: Configuration): D };
driverOptions: Dictionary;
namingStrategy?: { new(): NamingStrategy };
implicitTransactions?: boolean;
disableTransactions?: boolean;
Expand Down Expand Up @@ -574,7 +574,7 @@ export interface MikroORMOptions<D extends IDatabaseDriver = IDatabaseDriver, EM
flushMode: FlushMode | 'commit' | 'auto' | 'always';
entityRepository?: EntityClass<EntityRepository<any>>;
entityManager?: Constructor<EM>;
replicas?: Partial<ConnectionOptions>[];
replicas?: ConnectionOptions[];
strict: boolean;
validate: boolean;
validateRequired: boolean;
Expand Down
4 changes: 2 additions & 2 deletions packages/knex/src/AbstractSqlConnection.ts
Expand Up @@ -179,7 +179,7 @@ export abstract class AbstractSqlConnection extends Connection {
}

protected createKnexClient(type: string): Knex {
const driverOptions = this.config.get('driverOptions');
const driverOptions = this.config.get('driverOptions')!;

if (driverOptions.context?.client instanceof knex.Client) {
this.logger.log('info', 'Reusing knex client provided via `driverOptions`');
Expand All @@ -199,7 +199,7 @@ export abstract class AbstractSqlConnection extends Connection {
client: type,
connection: this.getConnectionOptions(),
pool: this.config.get('pool'),
}, this.config.get('driverOptions'));
}, this.config.get('driverOptions'), this.options.driverOptions);
const options = config.connection as ConnectionOptions;
const password = options.password;

Expand Down
5 changes: 4 additions & 1 deletion tests/bootstrap.ts
Expand Up @@ -127,7 +127,10 @@ export async function initORMMySql<D extends MySqlDriver | MariaDbDriver = MySql
populateAfterFlush: false,
entityRepository: SqlEntityRepository,
driver: type === 'mysql' ? MySqlDriver : MariaDbDriver,
replicas: [{ name: 'read-1' }, { name: 'read-2' }], // create two read replicas with same configuration, just for testing purposes
replicas: [
{ name: 'read-1', driverOptions: { connection: { enableKeepAlive: true } } },
{ name: 'read-2', driverOptions: { connection: { enableKeepAlive: false } } },
],
migrations: { path: BASE_DIR + '/../temp/migrations', snapshot: false },
extensions: [Migrator, SeedManager, EntityGenerator],
subscribers: [new Test2Subscriber()],
Expand Down

0 comments on commit 05e81f8

Please sign in to comment.