Skip to content

Commit

Permalink
fix(core): respect read replica options
Browse files Browse the repository at this point in the history
Closes #1963
  • Loading branch information
B4nan committed Aug 26, 2021
1 parent 544583b commit 0d203d5
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 11 deletions.
32 changes: 21 additions & 11 deletions packages/core/src/connections/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@ export abstract class Connection {

protected metadata!: MetadataStorage;
protected platform!: Platform;
protected readonly options: ConnectionOptions;
protected abstract client: any;

constructor(protected readonly config: Configuration,
protected readonly options?: ConnectionOptions,
options?: ConnectionOptions,
protected readonly type: 'read' | 'write' = 'write') {
if (!this.options) {
if (options) {
this.options = options;
} else {
const props = ['dbName', 'clientUrl', 'host', 'port', 'user', 'password', 'multipleStatements', 'pool'] as const;
this.options = props.reduce((o, i) => { (o[i] as any) = this.config.get(i); return o; }, {} as ConnectionOptions);
this.options = props.reduce((o, i) => {
(o[i] as any) = this.config.get(i);
return o;
}, {} as ConnectionOptions);
}
}

Expand All @@ -36,7 +42,11 @@ export abstract class Connection {
/**
* Closes the database connection (aka disconnect)
*/
abstract close(force?: boolean): Promise<void>;
async close(force?: boolean): Promise<void> {
Object.keys(this.options)
.filter(k => k !== 'name')
.forEach(k => delete this.options[k]);
}

/**
* Returns default client url for given driver (e.g. mongodb://127.0.0.1:27017 for mongodb)
Expand All @@ -63,12 +73,12 @@ export abstract class Connection {

getConnectionOptions(): ConnectionConfig {
const ret: ConnectionConfig = {};
const url = new URL(this.options!.clientUrl || this.config.getClientUrl());
this.options!.host = ret.host = this.config.get('host', url.hostname);
this.options!.port = ret.port = this.config.get('port', +url.port);
this.options!.user = ret.user = this.config.get('user', url.username);
this.options!.password = ret.password = this.config.get('password', url.password);
this.options!.dbName = ret.database = this.config.get('dbName', url.pathname.replace(/^\//, ''));
const url = new URL(this.options.clientUrl ?? this.config.getClientUrl());
this.options.host = ret.host = this.options.host ?? this.config.get('host', url.hostname);
this.options.port = ret.port = this.options.port ?? this.config.get('port', +url.port);
this.options.user = ret.user = this.options.user ?? this.config.get('user', url.username);
this.options.password = ret.password = this.options.password ?? this.config.get('password', url.password);
this.options.dbName = ret.database = this.options.dbName ?? this.config.get('dbName', url.pathname.replace(/^\//, ''));

return ret;
}
Expand Down Expand Up @@ -120,7 +130,7 @@ export abstract class Connection {
let msg = query + (Utils.isDefined(took) ? c.grey(` [took ${took} ms]`) : '');

if (this.config.get('replicas', []).length > 0) {
msg += c.cyan(` (via ${this.type} connection '${this.options!.name || this.config.get('name') || this.options!.host}')`);
msg += c.cyan(` (via ${this.type} connection '${this.options.name || this.config.get('name') || this.options.host}')`);
}

logger.log('query', msg);
Expand Down
1 change: 1 addition & 0 deletions packages/knex/src/AbstractSqlConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export abstract class AbstractSqlConnection extends Connection {
}

async close(force?: boolean): Promise<void> {
await super.close(force);
await this.client.destroy();
}

Expand Down
2 changes: 2 additions & 0 deletions packages/knex/src/schema/SchemaGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export class SchemaGenerator {
this.config.set('dbName', this.helper.getManagementDbName());
await this.driver.reconnect();
await this.createDatabase(dbName);
this.config.set('dbName', dbName);
await this.driver.reconnect();
}
}

Expand Down
30 changes: 30 additions & 0 deletions tests/EntityManager.postgre.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1824,6 +1824,36 @@ describe('EntityManagerPostgre', () => {
expect(updates).toHaveLength(0);
});

test('getConnection() with replicas (GH issue #1963)', async () => {
const config = new Configuration({
type: 'postgresql',
clientUrl: 'postgre://root@127.0.0.1:1234/db_name',
host: '127.0.0.10',
password: 'secret',
user: 'user',
logger: jest.fn(),
forceUtcTimezone: true,
replicas: [
{ name: 'read-1', host: 'read_host_1', user: 'read_user' },
],
} as any, false);
const driver = new PostgreSqlDriver(config);
expect(driver.getConnection('write').getConnectionOptions()).toEqual({
database: 'db_name',
host: '127.0.0.10',
password: 'secret',
user: 'user',
port: 1234,
});
expect(driver.getConnection('read').getConnectionOptions()).toEqual({
database: 'db_name',
host: 'read_host_1',
password: 'secret',
user: 'read_user',
port: 1234,
});
});

// this should run in ~600ms (when running single test locally)
test('perf: one to many', async () => {
const author = new Author2('Jon Snow', 'snow@wall.st');
Expand Down

0 comments on commit 0d203d5

Please sign in to comment.