1
1
import { join } from 'path' ;
2
- import { createServer } from 'http' ;
2
+ import { createServer , Server } from 'http' ;
3
3
import { cpus } from 'os' ;
4
4
import * as cluster from 'cluster' ;
5
5
import * as spdy from 'spdy' ;
@@ -17,67 +17,59 @@ import {SessionManager} from './services/session';
17
17
import { HelpersService } from './services/helpers' ;
18
18
import { LoggingService } from './services/logger' ;
19
19
import { AuthService } from './services/auth' ;
20
+ import { HealthService } from './services/health' ;
21
+
22
+ dotenv . config ( { } ) ;
23
+ const loggingService = new LoggingService ( ) ;
20
24
21
- dotenv . config ( {
22
- debug : false // enable to see logs for set vars
23
- } ) ;
24
25
const APP_CONFIG : Config = {
25
26
environment : process . env . ENVIRONMENT || 'dev' ,
26
27
cookie_name : process . env . COOKIE_NAME || '__cookie_name' ,
27
- cookie_secret : process . env . COOKIE_SECRET || 'cookie_secret' ,
28
28
port : ( + process . env . NODE_PORT ) || 3000 ,
29
29
log_level : process . env . MORGAN_LOG_LEVEL || 'short' ,
30
30
client_root : process . env . CLIENT_ROOT || join ( __dirname , '../client/' ) ,
31
31
max_workers : + ( process . env . MAX_WORKERS || cpus ( ) . length ) ,
32
+ logger : loggingService ,
33
+ healthService : new HealthService ( loggingService ) ,
32
34
} ;
33
35
36
+ APP_CONFIG . healthService . init ( ) ;
37
+
38
+
34
39
if ( cluster . isMaster ) {
35
40
const numCPUs = Math . max ( 2 , Math . min ( cpus ( ) . length , APP_CONFIG . max_workers ) ) ;
36
- const workers : cluster . Worker [ ] = [ ] ;
37
- console . log ( '[ master ]: App starting on port' , APP_CONFIG . port ) ;
38
- console . log ( `[ master ]: Spinning up ${ numCPUs - 1 } workers` ) ;
39
- for ( let i = 1 ; i < numCPUs ; i ++ ) {
41
+ loggingService . log ( '[ master ]: App starting on port' , APP_CONFIG . port ) ;
42
+ loggingService . log ( `[ master ]: Spinning up ${ numCPUs - 1 } workers` ) ;
43
+ for ( let i = 1 ; i < numCPUs ; i ++ ) {
40
44
const worker = HelpersService . forkWorker ( ) ;
41
- workers . push ( worker ) ;
42
45
}
43
46
44
- cluster . on ( 'listening' , ( worker ) => {
45
- console . log ( `[ worker ${ worker . id } ]: Ready and listening!` ) ;
46
- } ) ;
47
-
48
- cluster . on ( 'message' , ( worker , messages , handle ) => {
49
- if ( Array . isArray ( messages ) && messages . shift ( ) === 'console' ) {
50
- console . log ( `[ worker ${ worker . id } ]:` , ...messages ) ;
51
- }
52
- } ) ;
53
-
54
47
cluster . on ( 'exit' , ( worker , code , signal ) => {
55
- const deadIndex = workers . findIndex ( w => w . id === worker . id ) ;
56
- if ( deadIndex >= 0 ) {
57
- workers . splice ( deadIndex , 1 ) ;
58
- }
48
+ APP_CONFIG . healthService . checkClusterHealth ( ) ;
59
49
if ( ! worker . exitedAfterDisconnect ) {
60
- console . log ( `[ master ]: replacing crashed worker ${ worker . id } ` ) ;
50
+ loggingService . log ( `[ master ]: replacing crashed worker ${ worker . id } ` ) ;
61
51
const newWorker = HelpersService . forkWorker ( ) ;
62
- workers . push ( newWorker ) ;
63
52
}
64
53
} ) ;
65
54
66
- process . on ( 'exit ' , ( ) => {
67
- console . log ( '[ master ]: killing workers' ) ;
68
- workers . forEach ( ( worker ) => worker . kill ( ) ) ;
55
+ cluster . on ( 'listening ' , ( worker ) => {
56
+ loggingService . log ( `[ worker ${ worker . id } ]: Ready and Listening` ) ;
57
+ APP_CONFIG . healthService . setHealthy ( true ) ;
69
58
} ) ;
70
59
71
- } else {
72
- const loggingService = new LoggingService ( ) ;
73
- APP_CONFIG . logger = loggingService ;
74
60
61
+ // process.on('exit', () => {
62
+ // console.log('[ master ]: killing workers');
63
+ // workers.forEach((worker) => worker.kill());
64
+ // });
65
+
66
+ } else {
75
67
const app = express ( ) ;
76
68
app . use ( compress ( ) ) ;
77
69
app . use ( userAgent . express ( ) ) ;
78
70
app . use ( bodyParser . json ( { limit : '100mb' } ) ) ;
79
71
app . use ( bodyParser . urlencoded ( { limit : '50mb' , extended : true } ) ) ;
80
- app . use ( cookieParser ( APP_CONFIG . cookie_secret ) ) ;
72
+ app . use ( cookieParser ( process . env . COOKIE_SECRET || ' cookie_secret' ) ) ;
81
73
app . use (
82
74
morgan (
83
75
APP_CONFIG . log_level || ( ( tokens , req , res ) => LoggingService . customLogger ( tokens , req , res ) ) ,
@@ -87,6 +79,13 @@ if (cluster.isMaster) {
87
79
)
88
80
) ;
89
81
82
+ app . use ( ( req , res , next ) => {
83
+ if ( ! APP_CONFIG . healthService . isHealthy ( ) ) {
84
+ res . set ( 'connection' , 'close' ) ;
85
+ }
86
+ return next ( ) ;
87
+ } )
88
+
90
89
// redirect http to https
91
90
app . use ( require ( './middleware/httpredir' ) ( APP_CONFIG ) ) ;
92
91
@@ -101,7 +100,8 @@ if (cluster.isMaster) {
101
100
return next ( ) ;
102
101
} ) ;
103
102
104
- let server ;
103
+ let server : Server ;
104
+ let redir ;
105
105
if ( process . env . HTTPS ) {
106
106
let ssl_config = {
107
107
key : ( process . env . SSLKEY ? HelpersService . tryLoad ( process . env . SSLKEY ) : undefined ) ,
@@ -110,21 +110,25 @@ if (cluster.isMaster) {
110
110
pfx : ( process . env . SSLPFX ? HelpersService . tryLoad ( process . env . SSLPFX ) : undefined )
111
111
} ;
112
112
server = spdy . createServer ( ssl_config , app ) ;
113
- let redir = express ( ) ;
114
- redir . get ( '*' , ( req , res , next ) => {
115
- let httpshost = `https://${ req . headers . host } ${ req . url } ` ;
116
- return res . redirect ( httpshost ) ;
113
+ const redirApp = express ( ) ;
114
+ redirApp . get ( '*' , ( req , res , next ) => {
115
+ let httpshost = `https://${ req . headers . host } ${ req . url } ` ;
116
+ return res . redirect ( httpshost ) ;
117
117
} ) ;
118
- redir . listen ( 80 ) ;
118
+ APP_CONFIG . healthService . registerServer ( redir ) ;
119
+ redir = redirApp . listen ( 80 ) ;
119
120
} else {
120
121
server = createServer ( app ) ;
121
122
}
122
123
123
124
/*-------- Services --------*/
124
125
const db = new DatabaseService ( ) ;
125
126
APP_CONFIG . db = db ;
127
+ APP_CONFIG . healthService . registerService ( db ) ;
128
+
126
129
const sessionManager = new SessionManager ( db ) ;
127
130
APP_CONFIG . sessionManager = sessionManager ;
131
+
128
132
const authService = new AuthService ( db , loggingService ) ;
129
133
APP_CONFIG . authService = authService ;
130
134
@@ -151,9 +155,8 @@ if (cluster.isMaster) {
151
155
return res . status ( 404 ) . send ( { Message : '404 UNKNOWN ROUTE' } ) ;
152
156
} ) ;
153
157
154
- server . listen ( APP_CONFIG . port ) ;
155
-
156
- if ( cluster . isMaster ) {
157
- console . log ( 'APP LISTENING ON PORT' , APP_CONFIG . port ) ;
158
- }
158
+ APP_CONFIG . healthService . registerServer ( server ) ;
159
+ server . listen ( APP_CONFIG . port , ( ) => {
160
+ APP_CONFIG . healthService . setHealthy ( true ) ;
161
+ } ) ;
159
162
}
0 commit comments