UNPKG

16.4 kBTypeScriptView Raw
1/// <reference types="node" />
2
3/**
4 * contains all of your service's dependencies and provides scheduling
5 * options for checking those dependencies
6 */
7interface Copacetic extends NodeJS.EventEmitter {
8 /**
9 * The name of your service. This is output in the express
10 * middleware when verbose is true
11 */
12 name: string,
13
14 /**
15 * Whether dependencies are currently being polled
16 */
17
18 isPolling: boolean,
19
20 /**
21 * True when there are no hard dependency failures
22 */
23 isHealthy: boolean,
24
25 /**
26 * When true, 'check' and 'waitFor' will return an instance
27 * of Copacetic, if false a promise will be returned. It should
28 * be noted that polling is unaffected by this field, and will
29 * always return the Copacetic instance in use.
30 */
31 eventEmitterMode: boolean,
32
33 /**
34 * Health information on all registered services
35 */
36 healthInfo: Array<copacetic.Health>,
37
38 /**
39 * A full health report
40 */
41 healthReport: {
42 isHealthy: boolean,
43 name: string,
44 dependencies: Array<copacetic.Health>
45 }
46
47 /**
48 * Returns a registered dependency
49 * Examples:
50 *
51 * // With a name
52 * copacetic.getDependency('database')
53 *
54 * // With a dependency
55 * copacetic.getDependency(dep)
56 */
57 getDependency (dependency: copacetic.Dependency|string): copacetic.Dependency,
58
59 /**
60 * Checks if a dependency exists
61 * Examples:
62 *
63 * // With a name
64 * copacetic.isDependencyRegistered('database')
65 *
66 * // With a dependency
67 * copacetic.isDependencyRegistered(dep)
68 */
69 isDependencyRegistered (dependency: copacetic.Dependency|string): copacetic.Dependency,
70
71 /**
72 * Adds a dependency to a copacetic instance
73 * Examples:
74 *
75 * copacetic.registerDependency({ name: 'database', url: 'memes.com' })
76 *
77 * copacetic.registerDependency({ name: 'cache', strategy: { type: 'redis' } })
78 *
79 * copacetic
80 * .registerDependency
81 * ({ name: 'service', strategy: { type: 'redis', adapter } })
82 */
83 registerDependency (options: copacetic.DependencyOptions): Copacetic,
84
85 /**
86 * Removes a dependency from a copacetic instance
87 * Examples:
88 *
89 * // With a name
90 * copacetic.deregisterDependency('database')
91 *
92 * // With a dependency
93 * copacetic.deregisterDependency(dep)
94 */
95 deregisterDependency (dependency: copacetic.Dependency|string): Copacetic,
96
97 /**
98 * Polls the health of all registered dependencies
99 */
100 pollAll (options: {
101 /**
102 * The rate at which dependencies will be polled, of the format
103 * '5 seconds', '1m minute 20 seconds' etc.
104 */
105 interval?: string,
106
107 /**
108 * check the health of dependencies in sequence, or parallel
109 */
110 parallel?: boolean,
111
112 /**
113 * Schedule the next check as soon as a poll starts, or wait
114 */
115 schedule?: string
116 }): Copacetic,
117
118 /**
119 * Polls the health of a single dependency
120 * Example:
121 *
122 * copacetic.poll({
123 * name: 'database',
124 * interval: '1 minute 30 seconds',
125 * parallel: false
126 * })
127 */
128 poll (options: {
129 /*
130 * The name used when registering the dependency
131 */
132 name: string,
133
134 /**
135 * The rate at which dependencies will be polled, of the format
136 * '5 seconds', '1m minute 20 seconds' etc.
137 */
138 interval?: string,
139
140 /**
141 * Check the health of dependencies in sequence, or parallel
142 */
143 parallel?: boolean,
144
145 /**
146 * Schedule the next check as soon as a poll starts, or wait
147 */
148 schedule?: string
149 }): Copacetic,
150
151 /**
152 * Polls the health of a set of dependencies
153 * Example:
154 *
155 * copacetic.poll({
156 * dependencies: [
157 * { name: 'database', retries: 2 },
158 * { name: 'cache' }
159 * ],
160 * interval: '1 minute 30 seconds'
161 * parallel: false
162 * })
163 */
164 poll (options: {
165 /**
166 * The dependencies to be health checked
167 */
168 dependencies: Array<
169 {
170 /*
171 * The name used when registering the dependency
172 */
173 name: string,
174 /*
175 * The number of times to retry a health check, before marking as unhealthy
176 */
177 retries?: number,
178 /*
179 * The maximum interval of time to wait when retrying
180 */
181 maxDelay?: number
182 }
183 >,
184 /**
185 * The rate at which dependencies will be polled, of the format
186 * '5 seconds', '1m minute 20 seconds' etc.
187 */
188 interval?: string,
189 /**
190 * Check the health of dependencies in sequence, or parallel
191 */
192 parallel?: boolean,
193 /**
194 * Schedule the next check as soon as a poll starts, or wait
195 */
196 schedule?: string
197 }): Copacetic,
198
199
200 /**
201 * stops polling dependencies
202 */
203 stop (): void,
204
205 /**
206 * Checks the health of all registered dependencies
207 * Example:
208 *
209 * copacetic.checkAll(false)
210 */
211 checkAll (
212 /**
213 * Check the health of dependencies in sequence, or parallel
214 */
215 parallel: boolean
216 ): Copacetic | Promise<Array<copacetic.Health>>,
217
218 /**
219 * Checks the health of a single dependency
220 * Example:
221 * // when in event emitter mode
222 * copacetic.check({ name: 'database' }).on('healthy', () => {})
223 * copacetic.check({ name: 'cache', retries: 2 }).on('healthy', () => {})
224 *
225 * // when in promise mode
226 * copacetic.check<Promise<Copacetic.Health>>({ name: 'database' })
227 * .then((res) => { ... })
228 */
229 check<R = Copacetic> (options: {
230 /*s
231 * The name used when registering the dependency
232 */
233 name: string,
234
235 /*
236 * The number of times to retry a health check, before marking as unhealthy
237 */
238 retries?: number,
239
240 /*
241 * The maximum interval of time to wait when retrying
242 */
243 maxDelay?: number
244 }): R,
245
246 /**
247 * Checks the health of a set of dependencies
248 * Example:
249 * // when in event emitter mode
250 * copacetic.check({
251 * dependencies: [
252 * { name: 'database', retries: 2 },
253 * { name: 'cache' }
254 * ],
255 * parallel: false
256 * })
257 * .on('healthy', (health: Copacetic.Health) => { ... })
258 * .on('unhealthy', (health: Copacetic.Health) => { ... })
259 *
260 * // when in promise mode
261 * copacetic.check<Promise<Array<Copacetic.Health>>>({ dependencies })
262 * .then((res) => { ... })
263 *
264 */
265 check<R = Copacetic> (options: {
266 /**
267 * The dependencies to be health checked
268 */
269 dependencies: Array<
270 {
271 /*
272 * The name used when registering the dependency
273 */
274 name: string,
275 /*
276 * The number of times to retry a health check, before marking as unhealthy
277 */
278 retries?: number,
279 /*
280 * The maximum interval of time to wait when retrying
281 */
282 maxDelay?: number
283 }
284 >,
285
286 /**
287 * Check the health of dependencies in sequence, or parallel
288 */
289 parallel?: boolean
290 }): R,
291
292 /**
293 * If in cluster mode and this instance has been attached to it, ask the master process for health information of the full cluster
294 */
295 checkCluster: function () :Promise<Copacetic.healthReport>
296
297 /**
298 * Waits for a single dependency to become healthy
299 * Example:
300 * // when in event emitter mode
301 * copacetic.waitFor({ name: 'database' })
302 * .on('healthy', (health: Copacetic.Health) => { ... })
303 *
304 * // when in promise mode
305 * copacetic.waitFor<Copacetic.Health>({ name: 'database' })
306 * .then((res) => { ... })
307 */
308 waitFor<R = Copacetic> (options: {
309 /*
310 *the name used when registering the dependency
311 */
312 name: string,
313
314 /*
315 * The maximum interval of time to wait when retrying
316 */
317 maxDelay?: number
318 }): R
319
320 /**
321 * Waits for a set of dependencies to become healthy
322 * Example:
323 * // when in event emitter mode
324 * copacetic.waitFor({
325 * dependencies: [
326 * { name: 'database', maxDelay: '10 seconds' },
327 * { name: 'cache' }
328 * ],
329 * parallel: false
330 * })
331 * .on('healthy', (health: Copacetic.Health) => { ... })
332 *
333 * // when in promise mode
334 * copacetic.waitFor<Array<Copacetic.Health>>({
335 * dependencies: []
336 * }).then((res) => { ... })
337 *
338 */
339 waitFor<R = Copacetic> (options: {
340 /**
341 * The dependencies to be health checked
342 */
343 dependencies: Array<
344 {
345 /*
346 * The name used when registering the dependency
347 */
348 name: string,
349 /*
350 * The maximum interval of time to wait when retrying
351 */
352 maxDelay?: number
353 }
354 >,
355
356 /**
357 * Check the health of dependencies in sequence, or parallel
358 */
359 parallel?: boolean
360 }): R,
361
362 on (event: string | symbol, listener: Function): this,
363
364 /**
365 * Register an event listener for the 'health' event. Used when checking
366 * the health of a single dependency, i.e. copacetic.check({ name: '' })
367 */
368 on (
369 event: 'health',
370 listener: (payload: Array<copacetic.Health>, stop: Function) => void
371 ): this,
372
373 /**
374 * Register an event listener for 'healthy' event. used when checking
375 * the health of multiple dependencies, i.e. copacetic.check({ dependencies })
376 */
377 on (
378 event: 'healthy',
379 listener: (payload: copacetic.Health , stop: Function) => void
380 ): this,
381
382 /**
383 * Register an event listener for 'unhealthy' event. used when checking
384 * the health of multiple dependencies, i.e. copacetic.check({ dependencies })
385 */
386 on (
387 event: 'unhealthy',
388 listener: (payload: copacetic.Health, stop: Function) => void
389 ): this,
390}
391
392
393declare function Copacetic (
394 /**
395 * The name of your service. This is output in the express
396 * middleware when verbose is true
397 */
398 name?: string,
399 /**
400 * By default when using check/checkAll/waitFor events are emitted.
401 * If eventEmitterMode is set to false then promises will be returned
402 * instead. poll/pollAll remain unaffected by this, and will always
403 * return an event emitter.
404 */
405 eventEmitterMode?: boolean
406): Copacetic
407
408declare namespace Copacetic {
409 /**
410 * holds information about the health of a dependency, and executes strategies for
411 * checking a dependency's health
412 */
413 interface Dependency {
414 /**
415 * The identifier used for the dependency
416 */
417 name: string,
418
419 /**
420 * The relationship between a service and dependency
421 */
422 level: dependencyLevel,
423
424 /**
425 * Whether the dependency passed a health check
426 */
427 healthy: boolean,
428
429 /**
430 * The method used for checking a dependencies health
431 */
432 healthStrategy: HealthStrategy,
433
434 /**
435 * How a health strategy will delay itself before executing again
436 */
437 backoffStrategy: BackoffStrategy,
438
439 /**
440 * The description of a dependency's health
441 */
442 healthSummary: Health,
443
444 /**
445 * sets a dependency's status to healthy
446 */
447 onHealthy (): void,
448
449 /**
450 * sets a dependency's status to unhealthy
451 */
452 onUnhealthy (): void,
453
454 /**
455 * performs any cleanup needed
456 */
457 cleanup (): void,
458
459 check (
460 /**
461 * The number of times a dependency's health will be checked
462 * before giving up
463 */
464 retries?: number,
465
466 /*
467 * The maximum interval of time to wait when retrying
468 */
469 maxDelay?: number
470 ): Promise<Health>,
471 }
472
473 /**
474 * The description of a dependency's health
475 */
476 export interface Health {
477 /**
478 * The name of the dependency that this health report belongs to
479 */
480 name: string,
481
482 /**
483 * Whether the dependency passed a health check
484 */
485 healthy: boolean,
486
487 /**
488 * The relationship between a service and dependency
489 */
490 level: dependencyLevel,
491
492 /**
493 * The last time the dependency was health checked
494 */
495 lastChecked: Date
496 }
497
498 /**
499 * A method for checking a dependencies health
500 */
501 export interface HealthStrategy {
502 new (
503 /**
504 * How long to wait until giving up. of the format
505 * '5 seconds', '1m minute 20 seconds' etc.
506 */
507 timeout: string
508 ) : HealthStrategy
509
510 /**
511 * Check a dependency's health
512 * Example:
513 *
514 * dependency
515 * .check('my-resource', '5 seconds')
516 * .then(() => { ... do something now it's healthy })
517 * .then(() => { ... handle degraded state })
518 */
519 check (
520 /**
521 * The resource accessed when checking the health of a dependency
522 */
523 url: string,
524
525 /**
526 * How long to wait until giving up. of the format
527 * '5 seconds', '1m minute 20 seconds' etc.
528 */
529 timeout: string
530 ) : Promise<boolean>
531
532 /**
533 * Perform any cleanup operation, if needed, when a dependency
534 * is no longer in used
535 * Example:
536 *
537 * dependency
538 * .cleanup()
539 * .then(() => { ... cleanup went OK })
540 * .then(() => { ... cleanup failed })
541 */
542 cleanup (...args: any[]) : Promise<boolean>
543 }
544
545 /**
546 * Some function that returns a promise
547 */
548 export interface BackOffCallable {
549 () : Promise<boolean>
550 }
551
552 /**
553 * A way of delaying some callable. Returns a promise after X
554 * retries
555 */
556 export interface BackoffStrategy {
557 new(
558 /*
559 * The number of times execute will try the callable before giving up
560 */
561 maxRetries: number,
562 /*
563 * The maximum interval of time to wait when retrying
564 */
565 maxDelay?: number
566 ) : BackoffStrategy
567
568 /**
569 * execute some function, retrying some set number of times before failing
570 */
571 execute (callable: BackOffCallable) : Promise<boolean>
572 }
573
574 /**
575 * Options used for creating a health strategy via the
576 * HealthStrategy factory
577 */
578 export interface HealthStrategyOptions {
579 /**
580 * The type of health strategy to use, i.e. http, mongodb, redis
581 */
582 type: 'http' | 'mongodb' | 'redis' | 'postgres',
583
584 /**
585 * The configuration options for the type of strategy you want to use
586 * i.e. timeout
587 */
588 opts?: object,
589
590 /**
591 * A custom adapter to use for a health strategy, i.e. you may want to use some
592 * library/database driver copacetic doesn't support out of the box
593 */
594 adapter?: Function
595 }
596
597 /**
598 * Options used for registering a new dependency
599 */
600 export interface DependencyOptions {
601 /**
602 * Configuration options for a health strategy
603 */
604 strategy?: HealthStrategyOptions,
605
606 /**
607 * The relationship between a service and dependency
608 */
609 level?: dependencyLevel,
610
611 /**
612 * The identifier used for a dependency
613 */
614 name: string,
615
616 /**
617 * The resource accessed when checking the health of a dependency
618 */
619 url: string
620 }
621
622 /**
623 * Options for using the express middleware
624 */
625 export interface MiddlewareOptions {
626 /**
627 * The instance of copacetic that will serve health information
628 */
629 copacetic: Copacetic,
630
631 /**
632 * The rate at which dependencies will be polled, of the format
633 * '5 seconds', '1m minute 20 seconds' etc.
634 */
635 interval?: string,
636
637 /**
638 * The dependencies to be health checked
639 */
640 dependencies?: Array<copacetic.Dependency>,
641
642 /**
643 * check the health of dependencies in sequence, or parallel
644 */
645 parallel?: boolean,
646
647 /**
648 * schedule the next check as soon as a poll starts, or wait
649 */
650 schedule?: string,
651
652 /**
653 * When true the middleware will output all health information
654 * for the registered dependencies. If not verbose, only a status code
655 * will be returned
656 */
657 verbose?: boolean
658 }
659
660 /**
661 * Describes the relationship between your service and a dependency
662 */
663 export enum dependencyLevel {
664 /**
665 * Your service cannot function when a hard dependency is unavailable
666 */
667 HARD,
668
669 /*
670 * Your service can still run, even if this dependency is unavailable
671 */
672 SOFT
673 }
674 /**
675 * Express middleware for a copacetic instance
676 */
677 export function Middleware(options: MiddlewareOptions): Function
678
679 /**
680 * Factory function for providing different health strategies
681 */
682 export function HealthStrategy(options: HealthStrategyOptions): Function
683
684 export namespace cluster {
685 interface AttachOptions {
686 dependency?: {
687 level: dependencyLevel
688 }
689 }
690 export function attach (copacetic: Copacetic, attachOptions?: AttachOptions): Function
691 }
692}
693
694export = Copacetic
695
\No newline at end of file