Skip to content

Commit

Permalink
Merge pull request #1427 from exogee-technology/fix/race-condition-on…
Browse files Browse the repository at this point in the history
…-database-connection

Fix / Race condition on database connection
  • Loading branch information
thekevinbrown authored Dec 6, 2024
2 parents e9237e2 + 2154ba8 commit 8595dc5
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 15 deletions.
2 changes: 2 additions & 0 deletions src/examples/databases/src/backend/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const pgConnection = {
dbName: process.env.POSTGRES_DB_NAME ?? 'todo_app',
user: process.env.POSTGRES_DB_USER ?? 'postgres',
password: process.env.POSTGRES_DB_PASSWORD ?? '',
host: process.env.POSTGRES_DB_HOST ?? 'localhost',
port: parseInt(process.env.POSTGRES_DB_PORT ?? '5432'),
},
};
Expand All @@ -23,6 +24,7 @@ export const myConnection = {
dbName: process.env.MYSQL_DB_NAME ?? 'todo_app',
user: process.env.MYSQL_DB_USER ?? 'root',
password: process.env.MYSQL_DB_PASSWORD ?? '',
host: process.env.MYSQL_DB_HOST ?? 'localhost',
port: parseInt(process.env.MYSQL_DB_PORT ?? '3306'),
},
};
35 changes: 23 additions & 12 deletions src/packages/mikroorm/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,8 @@ class DatabaseImplementation {
}

class ConnectionsManager {
private connections: Map<string, DatabaseImplementation>;

constructor() {
this.connections = new Map<string, DatabaseImplementation>();
}
private connections = new Map<string, DatabaseImplementation>();
private connectionPromises = new Map<string, Promise<DatabaseImplementation>>();

getConnections() {
return Array.from(this.connections.values());
Expand All @@ -301,21 +298,35 @@ class ConnectionsManager {
return databaseConnection;
}

public connect = async (id?: string, connectionOptions?: ConnectionOptions) => {
if (!id) throw new Error('Error: No id attached to connection.');

public connect = (id: string, connectionOptions: ConnectionOptions) => {
if (this.connections.has(id)) return this.connections.get(id);
const database = new DatabaseImplementation();
if (connectionOptions) await database.connect(connectionOptions);
logger.trace(`Saving database connection with id "${id}".`);
this.connections.set(id, database);

const connect = new Promise<DatabaseImplementation>((resolve, reject) => {
const database = new DatabaseImplementation();
database
.connect(connectionOptions)
.then(() => {
logger.trace(`Saving database connection with id "${id}".`);
this.connections.set(id, database);
resolve(database);
})
.catch(reject);
});

this.connectionPromises.set(id, connect);

return connect;
};

public database(id: string) {
logger.trace(`Finding database connection for id "${id}"`);
return this.connections.get(id);
}

public awaitableDatabase(id: string) {
return this.connectionPromises.get(id);
}

public async close(id: string) {
const database = this.database(id);
await database?.close();
Expand Down
11 changes: 8 additions & 3 deletions src/packages/mikroorm/src/provider/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,16 @@ export class MikroBackendProvider<D> implements BackendProvider<D> {
const connectionPlugin = {
name: connectionManagerId,
event: GraphweaverRequestEvent.OnRequest,
next: (_: GraphweaverRequestEvent, _next: GraphweaverPluginNextFunction) => {
next: async (_: GraphweaverRequestEvent, _next: GraphweaverPluginNextFunction) => {
logger.trace(`Graphweaver OnRequest plugin called`);

const connection = ConnectionManager.database(connectionManagerId);
if (!connection) throw new Error('No database connection found');
const connection = await ConnectionManager.awaitableDatabase(connectionManagerId);

if (!connection) {
throw new Error(
`No database connection found for connectionManagerId: ${connectionManagerId} after waiting for connection. This should not happen.`
);
}

return RequestContext.create(connection.orm.em, _next, {});
},
Expand Down

0 comments on commit 8595dc5

Please sign in to comment.