Skip to content

Commit 4b78644

Browse files
committed
Adds Health.js
1 parent 3002b25 commit 4b78644

File tree

4 files changed

+259
-3
lines changed

4 files changed

+259
-3
lines changed

spec/Health.spec.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
"use strict";
2+
/* Tests for Health reporting */
3+
4+
import Health from '../src/Health';
5+
6+
describe('Parse server health', () => {
7+
it('should have expected default health report', (done) => {
8+
expect(Health.getReport()).toEqual({
9+
status: 'ok'
10+
});
11+
12+
done();
13+
});
14+
15+
it('should return expected complex report', (done) => {
16+
Health.set('callback', function() {
17+
return 'fancy_status';
18+
});
19+
20+
done();
21+
});
22+
23+
it('should return ok for get default status', (done) => {
24+
const status = Health.get('status');
25+
expect(status).toBe('ok');
26+
27+
done();
28+
});
29+
30+
it('should set and get plain data', (done) => {
31+
const string = 'foo-boo!';
32+
Health.set('critical_status', string);
33+
expect(Health.get('critical_status')).toBe(string);
34+
expect(Health.getRaw('critical_status')).toBe(string);
35+
36+
const int = 42;
37+
Health.set('critical_status', int);
38+
expect(Health.get('critical_status')).toBe(int);
39+
expect(Health.getRaw('critical_status')).toBe(int);
40+
41+
done();
42+
});
43+
44+
it('should set and get data from a callback', (done) => {
45+
Health.set('realtime_status', function() {
46+
return 'super_good';
47+
});
48+
49+
// test plain get
50+
expect(Health.get('realtime_status')).toBe('super_good');
51+
52+
// test raw get
53+
expect(Health.getRaw('realtime_status') instanceof Function).toBe(true);
54+
55+
done();
56+
});
57+
58+
it('should empty report with clear all', (done) => {
59+
Health.reset();
60+
let all = Health.getAll();
61+
expect(Object.keys(all).length > 0).toBe(true);
62+
63+
Health.clearAll();
64+
all = Health.getAll();
65+
expect(Object.keys(all).length).toBe(0);
66+
67+
done();
68+
});
69+
70+
it('should go back to default on reset', (done) => {
71+
Health.clearAll();
72+
const all = Health.getAll();
73+
expect(Object.keys(all).length).toBe(0);
74+
75+
Health.reset();
76+
expect(Health.get('status')).toBe('ok');
77+
78+
done();
79+
});
80+
81+
it('should add and override with setAll', (done) => {
82+
Health.setAll({
83+
status: 'new_status',
84+
running: 1,
85+
db: (() => {
86+
return 'good';
87+
})
88+
});
89+
90+
expect(Health.get('status')).toBe('new_status');
91+
expect(Health.get('running')).toBe(1);
92+
expect(Health.get('db')).toBe('good');
93+
94+
// reset
95+
Health.clearAll();
96+
Health.set('status', 'ok');
97+
98+
done();
99+
});
100+
101+
it('should remove data on clear', (done) => {
102+
const key = 'unneeded';
103+
104+
Health.set(key, 1);
105+
expect(Health.get(key)).toBe(1);
106+
107+
Health.clear(key);
108+
expect(Health.get(key)).toBe(undefined);
109+
110+
done();
111+
});
112+
113+
it('should remove callback on clear', (done) => {
114+
const key = 'callback';
115+
116+
Health.set(key, function() {
117+
return 'in_place';
118+
});
119+
expect(Health.get(key)).toBe('in_place');
120+
121+
Health.clear(key);
122+
expect(Health.get(key)).toBe(undefined);
123+
124+
done();
125+
});
126+
127+
it('should return null on unknown get', (done) => {
128+
expect(Health.get('not_a_known_item')).toBe(undefined);
129+
done();
130+
})
131+
});

spec/index.spec.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ describe('server', () => {
265265
url: 'http://localhost:8378/1/health',
266266
}, (error, response) => {
267267
expect(response.statusCode).toBe(200);
268+
console.dir(response.body);
268269
done();
269270
});
270271
});

src/Health.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
//
2+
// Holds configuration used for reporting server health statistics
3+
// Additional callbacks to get information for reporting can be registered here
4+
//
5+
6+
const Health = {
7+
8+
/**
9+
* Sets up our report with default data
10+
*/
11+
setup() {
12+
// reset to get started
13+
this.reset();
14+
},
15+
16+
/**
17+
* Returns the default report data
18+
*
19+
* @returns {{status: string}}
20+
*/
21+
getDefaultReportData() {
22+
return {
23+
status: 'ok'
24+
};
25+
},
26+
27+
/**
28+
* Gets the raw value for a given key
29+
*
30+
* @param {string }key Key to get value of
31+
*/
32+
getRaw(key) {
33+
return this.reportData[key];
34+
},
35+
36+
/**
37+
* Gets a particular value in our health report
38+
*
39+
* @param {string} key Key to get value of
40+
*/
41+
get(key) {
42+
const value = this.getRaw(key);
43+
if(!(value instanceof Function)) {
44+
// return data normally
45+
return value;
46+
} else {
47+
// return function result
48+
return value();
49+
}
50+
},
51+
52+
/**
53+
* Gets all data, replacing functions with their call results
54+
*
55+
* @returns {{}}
56+
*/
57+
getAll() {
58+
const all = {};
59+
for(const key in this.reportData) {
60+
all[key] = this.get(key);
61+
}
62+
return all;
63+
},
64+
65+
/**
66+
* Sets a key/value pair of our health report
67+
* The
68+
*
69+
* @param {string} key Key to set report data on
70+
* @param {string|int|Object|Function} value Report data to set, this can also be a callback
71+
*/
72+
set(key, value) {
73+
this.reportData[key] = value;
74+
},
75+
76+
/**
77+
* Sets all the given data on the current report, overriding any pre-existing data
78+
*
79+
* @param {Object} data
80+
*/
81+
setAll(data) {
82+
for(const key in data) {
83+
this.reportData[key] = data[key];
84+
}
85+
},
86+
87+
/**
88+
* Clears a given key for this report
89+
*
90+
* @param key
91+
*/
92+
clear(key) {
93+
delete this.reportData[key];
94+
},
95+
96+
/**
97+
* Clears all report data
98+
*/
99+
clearAll() {
100+
this.reportData = {};
101+
},
102+
103+
/**
104+
* Prepares and returns the current health report
105+
*
106+
* @returns {{status: string}|*}
107+
*/
108+
getReport() {
109+
// return our prepared report
110+
return this.getAll();
111+
},
112+
113+
/**
114+
* Resets the current report data to it's defaults
115+
*/
116+
reset() {
117+
this.reportData = this.getDefaultReportData();
118+
}
119+
120+
};
121+
122+
// reset to populate report data
123+
Health.setup();
124+
125+
module.exports = Health;

src/ParseServer.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { SessionsRouter } from './Routers/SessionsRouter';
3434
import { UsersRouter } from './Routers/UsersRouter';
3535
import { PurgeRouter } from './Routers/PurgeRouter';
3636
import { AudiencesRouter } from './Routers/AudiencesRouter';
37+
import Health from './Health';
3738

3839
import { ParseServerRESTController } from './ParseServerRESTController';
3940
import * as controllers from './Controllers';
@@ -138,9 +139,7 @@ class ParseServer {
138139
}));
139140

140141
api.use('/health', (function(req, res) {
141-
res.json({
142-
status: 'ok'
143-
});
142+
res.json(Health.getReport());
144143
}));
145144

146145
api.use('/', bodyParser.urlencoded({extended: false}), new PublicAPIRouter().expressRouter());

0 commit comments

Comments
 (0)