Skip to content

Commit e2e0834

Browse files
committed
init
1 parent 42a9e25 commit e2e0834

File tree

6 files changed

+6221
-1
lines changed

6 files changed

+6221
-1
lines changed

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
language: node_js
2+
node_js:
3+
- "6"
4+
- "8"
5+
- "10"

README.md

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,59 @@
11
# node-appstate
2-
Application state handler
2+
3+
[![TravisCI Build Status](https://travis-ci.org/vanioinformatika/node-appstate.svg?branch=master)](https://travis-ci.org/vanioinformatika/node-appstate)
4+
5+
Application state handler without dependency
6+
7+
Initializaion without callback (logger):
8+
9+
```javascript
10+
const appState = require('./appState')()
11+
```
12+
13+
Initialization with a simple logger:
14+
15+
```javascript
16+
const appState = require('./appState')((appState, newAppState) => {
17+
console.log(`App state has changed from ${appState} to ${newAppState}`)
18+
})
19+
```
20+
21+
You have two variables:
22+
23+
* appState: application state
24+
25+
* newAppState: new application state
26+
27+
You can use any logger library, for example pino.
28+
29+
```javascript
30+
let logger = require('pino')()
31+
const appState = require('./appState')((appState, newAppState) => {
32+
logger.warn(`App state has changed from ${appState} to ${newAppState}`)
33+
})
34+
```
35+
36+
Changing application state.
37+
38+
```javascript
39+
const appState = require('./appState')()
40+
appState.init()
41+
appState.running()
42+
appState.error()
43+
appState.stopped()
44+
```
45+
46+
**Application state values: INIT, ERROR, RUNNING, STOPPED**
47+
48+
## Best practice
49+
50+
Using state:
51+
52+
* RUNNING - application is running
53+
* STOPPED - application is running, but programmatically stopped
54+
* ERROR - application is running, but has a critical error (e.g.: DB connection error): app doesn't serves requests
55+
* INIT - application is starting, initialization: starting phase (app doesn't handle request)
56+
57+
Use a /health endpoint for load-balancers, and set to UP, if ```appState.get() === 'RUNNING'```, else DOWN.
58+
59+
You can change anytime the application state, for example under initialization process: persistent DB connection error => appState.error()

appState.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// RUNNING - application is running
2+
// STOPPED - application is running, but programmatically stopped
3+
// ERROR - application is running, but has a critical error (e.g.: DB connection error): app doesn't serves requests
4+
// INIT - application is starting, initialization: starting phase (app doesn't handle request)
5+
6+
// start state
7+
var appState = 'INIT'
8+
9+
/**
10+
* Callback has two params: cb(appState, newAppState)
11+
* - appState: application state actually
12+
* - newAppState: new application state
13+
* Tipical use case is when cb contains a logger function.
14+
*/
15+
module.exports = (cb) => {
16+
/**
17+
* Set application state to new state and loging it,
18+
* if state has changed.
19+
* @param String newAppState
20+
*/
21+
function changeAppState (newAppState) {
22+
if (appState !== newAppState) {
23+
if (cb) cb(appState, newAppState)
24+
appState = newAppState
25+
}
26+
}
27+
28+
// changing appState
29+
function init () {
30+
changeAppState('INIT')
31+
}
32+
function running () {
33+
changeAppState('RUNNING')
34+
}
35+
function error () {
36+
changeAppState('ERROR')
37+
}
38+
function stopped () {
39+
changeAppState('STOPPED')
40+
}
41+
42+
// reading appState
43+
function get () {
44+
return appState
45+
}
46+
return {init, running, error, stopped, get}
47+
}

appState.spec.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/* eslint-env mocha */
2+
const should = require('should') // eslint-disable-line
3+
const sinon = require('sinon')
4+
const shouldSinon = require('should-sinon') // eslint-disable-line
5+
6+
describe('appState', () => {
7+
it('handling undefined logger callback function', () => {
8+
const appState = require('./appState')()
9+
appState.get().should.equal('INIT')
10+
appState.running()
11+
appState.get().should.equal('RUNNING')
12+
})
13+
14+
it('handling logger callback function, logging changes', () => {
15+
const loggerCB = sinon.spy()
16+
const appState = require('./appState')(loggerCB)
17+
appState.init()
18+
loggerCB.should.be.calledOnce()
19+
// appState hasn't changed: called one
20+
appState.init()
21+
loggerCB.should.be.calledOnce()
22+
})
23+
24+
it('changed: logged', () => {
25+
const loggerCB = sinon.spy()
26+
const appState = require('./appState')(loggerCB)
27+
appState.running()
28+
loggerCB.should.be.calledOnce()
29+
appState.stopped()
30+
loggerCB.should.be.calledTwice()
31+
})
32+
33+
it('is logging', () => {
34+
sinon.spy(console, 'log')
35+
const logger = {
36+
info (appState, newAppState) { console.log(`App state has changed from ${appState} to ${newAppState}`) }
37+
}
38+
const appState = require('./appState')(logger.info)
39+
appState.init()
40+
console.log.should.be.calledOnce()
41+
console.log.should.be.calledWith('App state has changed from STOPPED to INIT')
42+
console.log.restore()
43+
})
44+
45+
it('is INIT', () => {
46+
const appState = require('./appState')()
47+
appState.init()
48+
appState.get().should.be.equal('INIT')
49+
})
50+
51+
it('is RUNNING', () => {
52+
const appState = require('./appState')()
53+
appState.running()
54+
appState.get().should.be.equal('RUNNING')
55+
})
56+
57+
it('is STOPPED', () => {
58+
const appState = require('./appState')()
59+
appState.stopped()
60+
appState.get().should.be.equal('STOPPED')
61+
})
62+
63+
it('is ERROR', () => {
64+
const appState = require('./appState')()
65+
appState.error()
66+
appState.get().should.be.equal('ERROR')
67+
})
68+
})

0 commit comments

Comments
 (0)