-
-
Notifications
You must be signed in to change notification settings - Fork 100
/
Copy pathhealth-check-executor.service.ts
108 lines (95 loc) · 2.99 KB
/
health-check-executor.service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { Injectable, BeforeApplicationShutdown } from '@nestjs/common';
import {
HealthIndicatorFunction,
HealthIndicatorResult,
} from '../health-indicator';
import { HealthCheckError } from '../health-check/health-check.error';
import {
HealthCheckResult,
HealthCheckStatus,
} from './health-check-result.interface';
import { isHealthCheckError } from '../utils';
/**
* Takes care of the execution of health indicators.
*
* @description
* The HealthCheckExecutor is standalone, so it can be used for
* the legacy TerminusBootstrapService and the HealthCheckService.
*
* On top of that, the HealthCheckExecutor uses the `BeforeApplicationShutdown`
* hook, therefore it must implement the `beforeApplicationShutdown`
* method as public. We do not want to expose that
* to the end-user.
*
* @internal
*/
@Injectable()
export class HealthCheckExecutor implements BeforeApplicationShutdown {
private isShuttingDown = false;
/**
* Executes the given health indicators.
* Implementation for v6 compatibility.
*
* @throws {Error} All errors which are not inherited by the `HealthCheckError`-class
*
* @returns the result of given health indicators
* @param healthIndicators The health indicators which should get executed
*/
async execute(
healthIndicators: HealthIndicatorFunction[],
): Promise<HealthCheckResult> {
const { results, errors } = await this.executeHealthIndicators(
healthIndicators,
);
return this.getResult(results, errors);
}
/**
* @internal
*/
beforeApplicationShutdown(): void {
this.isShuttingDown = true;
}
private async executeHealthIndicators(
healthIndicators: HealthIndicatorFunction[],
) {
const results: HealthIndicatorResult[] = [];
const errors: HealthIndicatorResult[] = [];
const result = await Promise.allSettled(healthIndicators.map((h) => h()));
result.forEach((res) => {
if (res.status === 'fulfilled') {
results.push(res.value);
} else {
const error = res.reason;
// Is not an expected error. Throw further!
if (!isHealthCheckError(error)) throw error;
// Is a expected health check error
errors.push((error as HealthCheckError).causes);
}
});
return { results, errors };
}
private getSummary(results: HealthIndicatorResult[]): HealthIndicatorResult {
return results.reduce(
(previous: any, current: any) => Object.assign(previous, current),
{},
);
}
private getResult(
results: HealthIndicatorResult[],
errors: HealthIndicatorResult[],
): HealthCheckResult {
const infoErrorCombined = results.concat(errors);
const info = this.getSummary(results);
const error = this.getSummary(errors);
const details = this.getSummary(infoErrorCombined);
let status: HealthCheckStatus = 'ok';
status = errors.length > 0 ? 'error' : status;
status = this.isShuttingDown ? 'shutting_down' : status;
return {
status,
info,
error,
details,
};
}
}