-
-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37 from nartc/mongo-health-check
feature(@nestjs/terminus) Add health check for mongoose ODM
- Loading branch information
Showing
30 changed files
with
9,091 additions
and
172 deletions.
There are no files selected for viewing
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 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 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 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 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,76 @@ | ||
import { INestApplication } from '@nestjs/common'; | ||
|
||
import Axios from 'axios'; | ||
import { MongooseHealthIndicator, TerminusModuleOptions } from '../../lib'; | ||
import { bootstrapModule } from '../helper/bootstrap-module'; | ||
|
||
describe('Mongoose Database Health', () => { | ||
let app: INestApplication; | ||
let port: number; | ||
|
||
const getTerminusOptions = ( | ||
db: MongooseHealthIndicator, | ||
): TerminusModuleOptions => ({ | ||
endpoints: [ | ||
{ | ||
url: '/health', | ||
healthIndicators: [async () => db.pingCheck('mongo')], | ||
}, | ||
], | ||
}); | ||
|
||
it('should check if the mongoose is available', async () => { | ||
[app, port] = await bootstrapModule( | ||
{ | ||
inject: [MongooseHealthIndicator], | ||
useFactory: getTerminusOptions, | ||
}, | ||
false, | ||
true, | ||
); | ||
|
||
const response = await Axios.get(`http://0.0.0.0:${port}/health`); | ||
expect(response.status).toBe(200); | ||
expect(response.data).toEqual({ | ||
status: 'ok', | ||
info: { mongo: { status: 'up' } }, | ||
}); | ||
}); | ||
|
||
it('should throw an error if runs into timeout error', async () => { | ||
[app, port] = await bootstrapModule( | ||
{ | ||
inject: [MongooseHealthIndicator], | ||
useFactory: (db: MongooseHealthIndicator): TerminusModuleOptions => ({ | ||
endpoints: [ | ||
{ | ||
url: '/health', | ||
healthIndicators: [ | ||
async () => db.pingCheck('mongo', { timeout: 1 }), | ||
], | ||
}, | ||
], | ||
}), | ||
}, | ||
false, | ||
true, | ||
); | ||
|
||
try { | ||
await Axios.get(`http://0.0.0.0:${port}/health`, {}); | ||
} catch (error) { | ||
expect(error.response.status).toBe(503); | ||
expect(error.response.data).toEqual({ | ||
status: 'error', | ||
error: { | ||
mongo: { | ||
status: 'down', | ||
message: expect.any(String), | ||
}, | ||
}, | ||
}); | ||
} | ||
}); | ||
|
||
afterEach(async () => await app.close()); | ||
}); |
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 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 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 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 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
77 changes: 77 additions & 0 deletions
77
lib/health-indicators/abstract/abstract-database-health-indicator.ts
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,77 @@ | ||
import { HealthCheckError } from '@godaddy/terminus'; | ||
import { Connection as MongooseConnection } from 'mongoose'; | ||
import { Connection } from 'typeorm'; | ||
import { ConnectionNotFoundError, TimeoutError } from '../../errors'; | ||
import { HealthIndicatorResult } from '../../interfaces'; | ||
import { TimeoutError as PromiseTimeoutError } from '../../utils'; | ||
import { DatabasePingCheckSettings } from '../databse-ping-check-settings.interface'; | ||
import { HealthIndicator } from './health-indicator'; | ||
|
||
/** | ||
* Abstract AbstractDatabaseHealthIndicator | ||
*/ | ||
export abstract class AbstractDatabaseHealthIndicator extends HealthIndicator { | ||
/** | ||
* Constructor with the connection | ||
* @param connection The underlying Connection instance from TypeOrm or Mongoose connection | ||
*/ | ||
protected constructor(protected connection: Connection | MongooseConnection) { | ||
super(); | ||
} | ||
|
||
/** | ||
* Pings a typeorm | ||
* @param connection The connection which the ping should get executed | ||
* @param timeout The timeout how long the ping should maximum take | ||
*/ | ||
protected abstract async pingDb( | ||
connection: Connection | MongooseConnection, | ||
timeout: number, | ||
): Promise<any>; | ||
|
||
/** | ||
* Checks if the typeorm responds in (default) 1000ms and | ||
* returns a result object corresponding to the result | ||
* @param key | ||
* @param options | ||
*/ | ||
async pingCheck( | ||
key: string, | ||
options: DatabasePingCheckSettings = {}, | ||
): Promise<HealthIndicatorResult> { | ||
let isHealthy = false; | ||
const connection = options.connection || this.connection; | ||
const timeout = options.timeout || 1000; | ||
|
||
if (!connection) { | ||
throw new ConnectionNotFoundError( | ||
this.getStatus(key, isHealthy, { | ||
message: 'Connection provider not found in application context', | ||
}), | ||
); | ||
} | ||
|
||
try { | ||
await this.pingDb(connection, timeout); | ||
isHealthy = true; | ||
} catch (err) { | ||
if (err instanceof PromiseTimeoutError) { | ||
throw new TimeoutError( | ||
timeout, | ||
this.getStatus(key, isHealthy, { | ||
message: `timeout of ${timeout}ms exceeded`, | ||
}), | ||
); | ||
} | ||
} | ||
|
||
if (isHealthy) { | ||
return this.getStatus(key, isHealthy); | ||
} else { | ||
throw new HealthCheckError( | ||
`${key} is not available`, | ||
this.getStatus(key, isHealthy), | ||
); | ||
} | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
lib/health-indicators/health-indicator.ts → ...h-indicators/abstract/health-indicator.ts
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
Oops, something went wrong.