Repository navigation
Expand file tree
/
Copy pathworker.js
More file actions
113 lines (100 loc) · 3.28 KB
/
Copy pathworker.js
File metadata and controls
113 lines (100 loc) · 3.28 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
105
106
107
108
109
110
111
112
113
'use strict';
const config = require('@zone-eu/wild-config');
const log = require('npmlog');
const imap = require('./imap');
const pop3 = require('./pop3');
const lmtp = require('./lmtp');
const prometheus = require('./prometheus');
const mcp = require('./mcp');
const api = require('./api');
const acme = require('./acme');
const tasks = require('./tasks');
const webhooks = require('./webhooks');
const indexer = require('./indexer');
const plugins = require('./lib/plugins');
const db = require('./lib/db');
const errors = require('./lib/errors');
// preload certificate files
require('./lib/certs');
// Services are started in the listed order. The metrics listener comes first so that a later
// service failing to start is still visible through wildduck_service_up before the process exits.
// A failure to connect to the database happens before any of this and is not observable this way.
const SERVICES = [
['Prometheus metrics server', prometheus],
['task runner', tasks.start],
['webhook runner', webhooks.start],
['indexer process', indexer.start],
['IMAP server', imap],
['POP3 server', pop3],
['LMTP server', lmtp],
['API server', api],
['MCP server', mcp],
['ACME server', acme]
];
/**
* Logs a fatal startup error and exits once the error has had a chance to be reported.
*
* @param {String} message Error description.
* @param {Error} err Error object.
* @returns {void}
*/
function fail(message, err) {
log.error('App', '%s. %s', message, err.message);
errors.notify(err);
setTimeout(() => process.exit(1), 3000);
}
/**
* Starts the listed services one after another.
*
* @param {Array} services List of [name, start] entries.
* @param {Function} callback Called once every service has started.
* @returns {void}
*/
function startServices(services, callback) {
let pos = 0;
let startNext = () => {
if (pos >= services.length) {
return callback();
}
let [name, start] = services[pos++];
start(err => {
if (err) {
return fail(`Failed to start ${name}`, err);
}
startNext();
});
};
startNext();
}
// Initialize database connection
db.connect(err => {
if (err) {
return fail('Failed to setup database connection', err);
}
startServices(SERVICES, () => {
// downgrade user and group if needed
if (config.group) {
try {
process.setgid(config.group);
log.info('App', 'Changed group to "%s" (%s)', config.group, process.getgid());
} catch (E) {
return fail(`Failed to change group to "${config.group}"`, E);
}
}
if (config.user) {
try {
process.setuid(config.user);
log.info('App', 'Changed user to "%s" (%s)', config.user, process.getuid());
} catch (E) {
return fail(`Failed to change user to "${config.user}"`, E);
}
}
plugins.init('receiver');
plugins.handler.load(() => {
log.verbose('Plugins', 'Plugins loaded');
plugins.handler.runHooks('init', [], () => {
log.info('App', 'All servers started, ready to process some mail');
});
});
});
});