-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathserver.js
More file actions
104 lines (90 loc) · 2.77 KB
/
Copy pathserver.js
File metadata and controls
104 lines (90 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
const { loadEnvFile } = require('node:process');
const { loadConfig } = require('./config');
const { version } = require('./package.json');
const { createApp } = require('./src/app');
const { createData } = require('./src/data');
const { createDatabase } = require('./src/database');
const { createLogger } = require('./src/logger');
async function main() {
loadOptionalEnvFile();
const config = loadConfig();
const { log } = createLogger(config);
const database = createDatabase(config, log);
const data = createData({ pool: database.pool, cache: database.cache, log });
const app = createApp({ config, data, log, healthCheck: database.healthCheck, version });
try {
await database.connect();
const server = await listen(app, config.web);
log('info', 'Server', `Server listening on ${config.web.host}:${server.address().port}`);
let stopping = false;
const stop = async (signal) => {
if (stopping) {
return;
}
stopping = true;
log('info', 'Server', `Received ${signal}; shutting down`);
try {
await closeServer(server);
await database.shutdown();
log('info', 'Server', 'Shutdown complete');
} catch (err) {
log('error', 'Server', 'Graceful shutdown failed', err);
process.exitCode = 1;
}
};
process.once('SIGINT', () => void stop('SIGINT'));
process.once('SIGTERM', () => void stop('SIGTERM'));
return { app, server, stop };
} catch (err) {
log('error', 'Server', 'Failed to start', err);
try {
await database.shutdown();
} catch (shutdownError) {
log('error', 'Server', 'Failed to clean up after startup error', shutdownError);
}
throw err;
}
}
function loadOptionalEnvFile() {
try {
loadEnvFile();
} catch (err) {
if (err.code !== 'ENOENT') {
throw err;
}
}
}
function listen(app, webConfig) {
return new Promise((resolve, reject) => {
const server = app.listen(webConfig.port, webConfig.host);
server.requestTimeout = 30000;
server.headersTimeout = 15000;
server.keepAliveTimeout = 5000;
server.once('error', reject);
server.once('listening', () => {
server.removeListener('error', reject);
resolve(server);
});
});
}
function closeServer(server) {
return new Promise((resolve, reject) => {
const forceClose = setTimeout(() => server.closeAllConnections(), 10000);
forceClose.unref();
server.close((err) => {
clearTimeout(forceClose);
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
if (require.main === module) {
main().catch((err) => {
process.stderr.write(`${err.stack || err.message}\n`);
process.exitCode = 1;
});
}
module.exports = { main, loadOptionalEnvFile, listen, closeServer };