UNPKG

14 kBMarkdownView Raw
1# Copacetic
2[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
3[![Coverage Status](https://coveralls.io/repos/github/fresh8/copacetic/badge.svg?branch=master)](https://coveralls.io/github/fresh8/copacetic?branch=master)
4[![CircleCI](https://circleci.com/gh/fresh8/copacetic.svg?style=svg)](https://circleci.com/gh/fresh8/copacetic)
5
6A package to help your service check the health of its dependencies.
7
8
9## Requirements
10Node v6.4.0 and above
11
12## Installation
13```
14npm install @fresh8/copacetic --save
15```
16
17#### Quick Start - Javascript
18```javascript
19const Copacetic = require('@fresh8/copacetic')
20const level = require('@fresh8/copacetic').dependencyLevel
21
22const copacetic = Copacetic()
23
24// Register a dependency
25copacetic.registerDependency({
26 name: 'My-Dependency',
27 url: 'https://my-Dependency.io',
28 // Defaults to SOFT
29 level: level.HARD
30})
31
32
33// Check its health
34copacetic
35 .check({
36 name: 'My-Dependency',
37 retries: 2
38 })
39 .on('healthy', (Dependency) => {
40 /**
41 * { name: 'My-Dependency',
42 * healthy: true/false,
43 * lastChecked: Date,
44 * level: 'SOFT'
45 * }
46 */
47 })
48 .on('unhealthy', (Dependency) => {
49 // Handle degraded state...
50 })
51
52// in promise mode
53copacetic.eventEmitterMode = false
54
55copacetic
56 .check({ name: 'my-web-service' })
57 .then((res) => {
58 console.log(`${res.name} is healthy!`)
59 })
60 .catch((err) => {
61 console.log(err)
62 })
63```
64
65#### Quick Start - Typescript
66```typescript
67import * as Copacetic from '@fresh8/copacetic'
68
69const copacetic = Copacetic('my-service')
70
71const myDependencyOverHttp : Copacetic.DependencyOptions = {
72 name: 'my-web-service',
73 url: 'http://example.com'
74}
75
76copacetic.registerDependency(myDependencyOverHttp)
77
78instance
79 .check({ name: 'my-web-service' })
80 .on('healthy', (res: Copacetic.Health) => {
81 // do something with your healthy dependency :)
82 })
83 .on('unhealthy', (res: Copacetic.Health) => {
84 // handle degraded state
85 })
86
87// in promise mode
88copacetic.eventEmitterMode = false
89
90async function waitForWebService () {
91 try {
92 const res = await instance
93 .check<Copacetic.Health>({ name: 'my-web-service' })
94
95 console.log(`${res.name} is healthy!`)
96 } catch (err) {
97 console.log(err)
98 }
99}
100```
101
102#### Quick Start - cluster mode
103```js
104
105const Copacetic = require('@fresh8/copacetic')
106const level = require('@fresh8/copacetic').dependencyLevel
107
108const copacetic = Copacetic("A name", false)
109
110Copacetic.cluster.attach(copacetic)
111
112if (process.worker) {
113 //register your usual dependencies like databases
114
115
116 //use the line below to have the worker ask the master process a full health report
117 copacetic.checkCluster() //`checkCluster` is only defined if the process is a worker and if you called `attach()`
118 .then(console.log)
119} else {
120 copacetic.checkAll()
121 .then(() => {
122 console.log(copacetic.healthReport) //Contains health information as reported by the workers
123 })
124}
125```
126
127## Classes
128
129<dl>
130<dt><a href="#Copacetic">Copacetic</a><code>EventEmitter</code></dt>
131<dd></dd>
132</dl>
133
134## Typedefs
135
136<dl>
137<dt><a href="#HealthReport">HealthReport</a> : <code>Object</code></dt>
138<dd><p>The full health report including isHealthy and dependencies</p>
139</dd>
140</dl>
141
142<a name="Copacetic"></a>
143
144## Copacetic ⇐ <code>EventEmitter</code>
145**Kind**: global class
146**Extends**: <code>EventEmitter</code>
147
148* [Copacetic](#Copacetic) ⇐ <code>EventEmitter</code>
149 * [new Copacetic([name])](#new_Copacetic_new)
150 * [.isHealthy](#Copacetic+isHealthy) ⇒ <code>Boolean</code>
151 * [.healthInfo](#Copacetic+healthInfo) ⇒ <code>Array.&lt;DependencyHealth&gt;</code>
152 * [.healthReport](#Copacetic+healthReport) ⇒ [<code>HealthReport</code>](#HealthReport)
153 * [.getDependency(dependency)](#Copacetic+getDependency) ⇒ <code>Dependency</code>
154 * [.isDependencyRegistered(dependency)](#Copacetic+isDependencyRegistered) ⇒ <code>Boolean</code>
155 * [.registerDependency(opts)](#Copacetic+registerDependency) ⇒ [<code>Copacetic</code>](#Copacetic)
156 * [.deregisterDependency(name)](#Copacetic+deregisterDependency) ⇒ [<code>Copacetic</code>](#Copacetic)
157 * [.pollAll([interval], [parallel], [schedule])](#Copacetic+pollAll) ⇒ [<code>Copacetic</code>](#Copacetic)
158 * [.poll([name], [dependencies], [interval], [parallel], [schedule])](#Copacetic+poll) ⇒ [<code>Copacetic</code>](#Copacetic)
159 * [.stop()](#Copacetic+stop)
160 * [.checkAll([parallel])](#Copacetic+checkAll) ⇒ [<code>Copacetic</code>](#Copacetic)
161 * [.check([name], [dependencies], [retries], [parallel])](#Copacetic+check) ⇒ [<code>Copacetic</code>](#Copacetic)
162 * [.waitFor(opts)](#Copacetic+waitFor)
163 * [._checkOne(name, maxDelay)](#Copacetic+_checkOne) ⇒ <code>Promise</code>
164 * [._checkMany(dependencies, parallel)](#Copacetic+_checkMany) ⇒ <code>Promise</code>
165 * ["healthy"](#Copacetic+event_healthy)
166 * ["unhealthy"](#Copacetic+event_unhealthy)
167 * ["health"](#Copacetic+event_health)
168
169<a name="new_Copacetic_new"></a>
170
171### new Copacetic([name])
172
173| Param | Type | Default | Description |
174| --- | --- | --- | --- |
175| [name] | <code>String</code> | <code>&#x27;&#x27;</code> | The name of your service |
176
177<a name="Copacetic+isHealthy"></a>
178
179### copacetic.isHealthy ⇒ <code>Boolean</code>
180**Kind**: instance property of [<code>Copacetic</code>](#Copacetic)
181**Returns**: <code>Boolean</code> - Copacetic is healthy when all hard dependencies are healthy
182<a name="Copacetic+healthInfo"></a>
183
184### copacetic.healthInfo ⇒ <code>Array.&lt;DependencyHealth&gt;</code>
185**Kind**: instance property of [<code>Copacetic</code>](#Copacetic)
186**Returns**: <code>Array.&lt;DependencyHealth&gt;</code> - Health information on all dependencies
187<a name="Copacetic+healthReport"></a>
188
189### copacetic.healthReport ⇒ [<code>HealthReport</code>](#HealthReport)
190**Kind**: instance property of [<code>Copacetic</code>](#Copacetic)
191**Returns**: [<code>HealthReport</code>](#HealthReport) - A full report of health information and dependencies
192<a name="Copacetic+getDependency"></a>
193
194### copacetic.getDependency(dependency) ⇒ <code>Dependency</code>
195**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
196
197| Param | Type |
198| --- | --- |
199| dependency | <code>Dependency</code> \| <code>String</code> |
200
201<a name="Copacetic+isDependencyRegistered"></a>
202
203### copacetic.isDependencyRegistered(dependency) ⇒ <code>Boolean</code>
204**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
205**Returns**: <code>Boolean</code> - Whether the dependency has been registered
206
207| Param | Type |
208| --- | --- |
209| dependency | <code>Dependency</code> \| <code>String</code> |
210
211<a name="Copacetic+registerDependency"></a>
212
213### copacetic.registerDependency(opts) ⇒ [<code>Copacetic</code>](#Copacetic)
214Adds a dependency to a Copacetic instance
215
216**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
217
218| Param | Type | Description |
219| --- | --- | --- |
220| opts | <code>Object</code> | The configuration for a dependency |
221
222<a name="Copacetic+deregisterDependency"></a>
223
224### copacetic.deregisterDependency(name) ⇒ [<code>Copacetic</code>](#Copacetic)
225Removes a dependency from a Copacetic instance
226
227**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
228
229| Param | Type | Description |
230| --- | --- | --- |
231| name | <code>String</code> | The name used to identify a dependency |
232
233<a name="Copacetic+pollAll"></a>
234
235### copacetic.pollAll([interval], [parallel], [schedule]) ⇒ [<code>Copacetic</code>](#Copacetic)
236Polls the health of all registered dependencies
237
238**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
239
240| Param | Type | Default |
241| --- | --- | --- |
242| [interval] | <code>String</code> | <code>&#x27;5 seconds&#x27;</code> |
243| [parallel] | <code>Boolean</code> | <code>true</code> |
244| [schedule] | <code>String</code> | <code>&#x27;start&#x27;</code> |
245
246<a name="Copacetic+poll"></a>
247
248### copacetic.poll([name], [dependencies], [interval], [parallel], [schedule]) ⇒ [<code>Copacetic</code>](#Copacetic)
249Polls the health of a set of dependencies
250
251**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
252**Emits**: [<code>health</code>](#Copacetic+event_health)
253
254| Param | Type | Default | Description |
255| --- | --- | --- | --- |
256| [name] | <code>String</code> | | The identifier of a single dependency to be checked |
257| [dependencies] | <code>Array.&lt;Object&gt;</code> | | An explicit set of dependencies to be polled |
258| [interval] | <code>String</code> | <code>&#x27;5 seconds&#x27;</code> | |
259| [parallel] | <code>Boolean</code> | <code>true</code> | Kick of health checks in parallel or series |
260| [schedule] | <code>String</code> | <code>&#x27;start&#x27;</code> | Schedule the next check to start (interval - ms) | ms |
261
262**Example**
263```js
264copacetic.poll({
265 dependencies: [
266 { name: 'my-dep' },
267 { name: 'my-other-dep', retries: 2, maxDelay: '2 seconds' }
268 ],
269 schedule: 'end',
270 interval: '1 minute 30 seconds'
271})
272.on('health', (serviceHealth, stop) => {
273 // Do something with the result
274 // [{ name: String, health: Boolean, level: HARD/SOFT, lastCheck: Date }]
275 // stop polling
276 stop()
277})
278```
279**Example**
280```js
281copacetic.poll({ name: 'my-dependency' })
282.on('health', () => { ... Do something })
283```
284<a name="Copacetic+stop"></a>
285
286### copacetic.stop()
287stops polling registered dependencies
288
289**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
290<a name="Copacetic+checkAll"></a>
291
292### copacetic.checkAll([parallel]) ⇒ [<code>Copacetic</code>](#Copacetic)
293Checks the health of all registered dependencies
294
295**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
296
297| Param | Type | Default | Description |
298| --- | --- | --- | --- |
299| [parallel] | <code>Boolean</code> | <code>true</code> | Kick of health checks in parallel or series |
300
301<a name="Copacetic+check"></a>
302
303### copacetic.check([name], [dependencies], [retries], [parallel]) ⇒ [<code>Copacetic</code>](#Copacetic)
304Checks the health of a set, or single dependency
305
306**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
307**Emits**: [<code>health</code>](#Copacetic+event_health), [<code>healthy</code>](#Copacetic+event_healthy), [<code>unhealthy</code>](#Copacetic+event_unhealthy)
308
309| Param | Type | Default | Description |
310| --- | --- | --- | --- |
311| [name] | <code>String</code> | | The identifier of a single dependency to be checked |
312| [dependencies] | <code>Array.&lt;Object&gt;</code> | | An explicit set of dependencies to be checked |
313| [retries] | <code>Integer</code> | <code>1</code> | How many times should a dependency be checked, until it is deemed unhealthy |
314| [parallel] | <code>Boolean</code> | <code>true</code> | Kick of health checks in parallel or series |
315
316**Example**
317```js
318copacetic.check({ name: 'my-dependency' })
319```
320**Example**
321```js
322copacetic.check({ name: 'my-dependency', retries: 5 })
323.on('healthy', serviceHealth => { ... Do stuff })
324.on('unhealthy', serviceHealth => { ... Handle degraded state })
325```
326**Example**
327```js
328copacetic.check({ dependencies: [
329 { name: 'my-dep' },
330 { name: 'my-other-dep', retries: 2, maxDelay: '1 second' }
331] })
332.on('health', (servicesHealth) => {
333 // Do something with the result
334 // [{ name: String, health: Boolean, level: HARD/SOFT, lastCheck: Date }]
335})
336```
337**Example**
338```js
339copacetic.check({ name: 'my-dependency' })
340.then((health) => { ... Do Stuff })
341.catch((err) => { ... Handle degraded state })
342```
343<a name="Copacetic+waitFor"></a>
344
345### copacetic.waitFor(opts)
346Convenience method that waits for a single, or set of dependencies
347to become healthy. Calling this means copacetic will keep re-checking
348indefinitely until the dependency(s) become healthy. If you want more
349control, use .check().
350
351**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
352
353| Param | Type | Description |
354| --- | --- | --- |
355| opts | <code>Object</code> | options accepted by check() |
356
357**Example**
358```js
359// wait indefinitely
360copacetic.waitFor({ name: 'my-dependency'})
361.on('healthy', serviceHealth => { ... Do stuff })
362```
363**Example**
364```js
365// give up after 5 tries
366copacetic.waitFor({ name: 'my-dependency', retries: 5})
367.on('healthy', serviceHealth => { ... Do stuff })
368```
369<a name="Copacetic+_checkOne"></a>
370
371### copacetic._checkOne(name, maxDelay) ⇒ <code>Promise</code>
372**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
373
374| Param | Type | Description |
375| --- | --- | --- |
376| name | <code>String</code> | The name used to identify a dependency |
377| maxDelay | <code>Integer</code> | The maximum interval of time to wait when retrying |
378
379<a name="Copacetic+_checkMany"></a>
380
381### copacetic._checkMany(dependencies, parallel) ⇒ <code>Promise</code>
382Checks an array of dependencies in parallel or sequantially
383
384**Kind**: instance method of [<code>Copacetic</code>](#Copacetic)
385
386| Param | Type |
387| --- | --- |
388| dependencies | <code>Array.&lt;Dependency&gt;</code> |
389| parallel | <code>Boolean</code> |
390
391<a name="Copacetic+event_healthy"></a>
392
393### "healthy"
394Health information on a single dependency
395
396**Kind**: event emitted by [<code>Copacetic</code>](#Copacetic)
397<a name="Copacetic+event_unhealthy"></a>
398
399### "unhealthy"
400Health information on a single dependency
401
402**Kind**: event emitted by [<code>Copacetic</code>](#Copacetic)
403<a name="Copacetic+event_health"></a>
404
405### "health"
406Health information on a set of dependencies
407
408**Kind**: event emitted by [<code>Copacetic</code>](#Copacetic)
409<a name="HealthReport"></a>
410
411## HealthReport : <code>Object</code>
412The full health report including isHealthy and dependencies
413
414**Kind**: global typedef
415**Properties**
416
417| Name | Type | Description |
418| --- | --- | --- |
419| isHealthy | <code>Boolean</code> | The result of [isHealthy](#Copacetic+isHealthy) |
420| Name | <code>String</code> | |
421| dependencies | <code>Array.&lt;DependencyHealth&gt;</code> | The result of [healthInfo](#Copacetic+healthInfo) |
422