Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(mongoRepo): Adds retries to connections. (#30)
- Loading branch information
Showing
12 changed files
with
144 additions
and
19 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { LoggerInstance } from 'winston'; | ||
import Connection from './Connection'; | ||
|
||
export default interface Config { | ||
readonly maxRetries: number; | ||
readonly retryGapMS: number; | ||
readonly logger: LoggerInstance; | ||
readonly url: string; | ||
readonly dbName: string; | ||
readonly setConnection: (connection: Promise<Connection>) => void; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { Db, MongoClient } from 'mongodb'; | ||
|
||
export default interface Connection { | ||
readonly client: MongoClient; | ||
readonly db: Db; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { MongoClient } from 'mongodb'; | ||
import Config from './Config'; | ||
import Connection from './Connection'; | ||
import handleJoiningReplica from './handleJoiningReplica'; | ||
import handleLeavingReplica from './handleLeavingReplica'; | ||
import retryConnection from './retryConnection'; | ||
|
||
export default async (config: Config, retries = 0): Promise<Connection> => { | ||
try { | ||
const client = await MongoClient.connect(config.url); | ||
const db = client.db(config.dbName); | ||
config.logger.info(`Created new Mongo connection`); | ||
(db as any).s.topology.once('left', handleLeavingReplica(config)); | ||
(db as any).s.topology.once('joined', handleJoiningReplica(config)); | ||
return { client, db }; | ||
} catch (err) { | ||
config.logger.error(`Failed Mongo connection: ${err.message}`); | ||
return retryConnection(config, retries + 1); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import Config from './Config'; | ||
import Connection from './Connection'; | ||
import createConnection from './createConnection'; | ||
import hasConnection from './hasConnection'; | ||
|
||
export default async ( | ||
config: Config, | ||
existingConnection?: Promise<Connection>, | ||
): Promise<Connection> => { | ||
const isConnected = await hasConnection(config, existingConnection); | ||
if (!isConnected) { | ||
return createConnection(config); | ||
} | ||
return existingConnection as Promise<Connection>; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import Config from './Config'; | ||
|
||
export default (config: Config) => (role: string, server: any) => { | ||
config.logger.info(`A ${role} server joined the replica set`, server.me); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import Config from './Config'; | ||
import createConnection from './createConnection'; | ||
|
||
export default (config: Config) => (role: string, server: any) => { | ||
config.logger.info(`A ${role} server (${server.ismaster.me}) left the replica set`); | ||
const connection = createConnection(config); | ||
connection.catch((err) => { | ||
config.logger.error(`Failed Mongo connection after server left the replica: ${err.message}`); | ||
}); | ||
config.setConnection(connection); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import * as mongodb from 'mongodb'; // tslint:disable-line:no-unused | ||
import Config from './Config'; | ||
import Connection from './Connection'; | ||
|
||
export default async (config: Config, connection: Promise<Connection> | undefined) => { | ||
if (connection === undefined) { | ||
return false; | ||
} | ||
try { | ||
const { client } = await connection; | ||
return client.isConnected(config.dbName); | ||
} catch (err) { | ||
return false; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Db } from 'mongodb'; | ||
import { LoggerInstance } from 'winston'; | ||
import Config from './Config'; | ||
import Connection from './Connection'; | ||
import getConnection from './getConnection'; | ||
|
||
export interface Opts { | ||
readonly maxRetries?: number; | ||
readonly retryGapMS?: number; | ||
readonly logger: LoggerInstance; | ||
readonly url: string; | ||
readonly dbName: string; | ||
} | ||
|
||
const defaultMaxRetries = 3; | ||
const defaultRetryGapMS = 1000; | ||
|
||
export default ({ | ||
maxRetries = defaultMaxRetries, | ||
retryGapMS = defaultRetryGapMS, | ||
logger, | ||
url, | ||
dbName, | ||
}: Opts) => { | ||
let connection: Promise<Connection>; // tslint:disable-line:no-let | ||
const setConnection = (newConnection: Promise<Connection>) => { | ||
connection = newConnection; | ||
}; | ||
const config: Config = { maxRetries, retryGapMS, logger, url, dbName, setConnection }; | ||
const connectToDb = async (): Promise<Db> => { | ||
setConnection(getConnection(config, connection)); | ||
return (await connection).db; | ||
}; | ||
connectToDb().catch((err) => { | ||
logger.error(`Failed initial mongo connection: ${err.message}`); | ||
}); | ||
return connectToDb; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { delay } from 'bluebird'; | ||
import Config from './Config'; | ||
import Connection from './Connection'; | ||
import createConnection from './createConnection'; | ||
|
||
export default async (config: Config, retries: number): Promise<Connection> => { | ||
if (retries > config.maxRetries) { | ||
throw new Error('Too many retries'); | ||
} | ||
config.logger.info(`Starting retry ${retries} in ${config.retryGapMS}ms`); | ||
await Promise.resolve(delay(config.retryGapMS)); | ||
return createConnection(config, retries); | ||
}; |