|
import { MongoClient } from 'mongodb' |
|
import { log } from '../log' |
|
import { connect } from './connect' |
|
|
|
let initiating = false |
|
let client: MongoClient | null = null |
|
|
|
/** |
|
* Queue of `resolve` and `reject` functions waiting for the result |
|
* of the on-going connection attempt. |
|
*/ |
|
let deferred: Array<{ |
|
resolve: (client: MongoClient) => void |
|
reject: (value: Error) => void |
|
}> = [] |
|
|
|
export const getSharedConnection = (): Promise<MongoClient> => { |
|
return new Promise(async (resolve, reject) => { |
|
// In case a connection is being initiated by another call... |
|
if (initiating) { |
|
// Defer resolving/rejecting to the end of that other execution |
|
log('mongo', 'already initiating, defer') |
|
deferred.push({ resolve, reject }) |
|
return |
|
} |
|
|
|
// In case there's already a connection established... |
|
if (client) { |
|
if (client.isConnected()) { |
|
// Client is connected, quick return |
|
resolve(client) |
|
return |
|
} else { |
|
// Client is not connected anymore, discard it and proceed |
|
client = null |
|
} |
|
} |
|
|
|
// No connection established or being established, so (re)connect |
|
initiating = true |
|
log('mongo', 'client init') |
|
try { |
|
client = await connect() |
|
// Connected with success |
|
log('mongo', 'connected') |
|
resolve(client) |
|
deferred.forEach(promise => promise.resolve(client!)) |
|
deferred = [] |
|
initiating = false |
|
} catch (error) { |
|
// Error |
|
client = null |
|
console.error('[mongo] client error:', error) |
|
reject(error) |
|
deferred.forEach(promise => promise.reject(error)) |
|
deferred = [] |
|
initiating = false |
|
} |
|
}) |
|
} |