pending-dns 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,37 @@
1
+ on:
2
+ push:
3
+ branches:
4
+ - master
5
+
6
+ name: Deploy instance
7
+
8
+ jobs:
9
+ deploy:
10
+ name: Deploy
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - name: Checkout
15
+ uses: actions/checkout@v2
16
+
17
+ - name: Install SSH key
18
+ uses: shimataro/ssh-key-action@v2
19
+ with:
20
+ key: ${{ secrets.SSH_KEY }}
21
+ known_hosts: ${{ secrets.KNOWN_HOSTS }}
22
+
23
+ - name: Deploy to server
24
+ env:
25
+ TARGET_HOST_01: dns-01.emailengine.app
26
+ TARGET_HOST_02: dns-02.emailengine.app
27
+ NODE_ENV: production
28
+ SERVICE_NAME: pending-dns
29
+ id: deploy
30
+ run: |
31
+ echo $GITHUB_SHA > commit.txt
32
+ npm install --production
33
+ tar czf /tmp/${SERVICE_NAME}.tar.gz --exclude .git .
34
+ scp /tmp/${SERVICE_NAME}.tar.gz deploy@${TARGET_HOST_01}:
35
+ scp /tmp/${SERVICE_NAME}.tar.gz deploy@${TARGET_HOST_02}:
36
+ ssh deploy@$TARGET_HOST_01 "/opt/deploy.sh ${SERVICE_NAME}"
37
+ ssh deploy@$TARGET_HOST_02 "/opt/deploy.sh ${SERVICE_NAME}"
package/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 Andris Reinman
3
+ Copyright (c) 2020-2023 Andris Reinman
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+ /* eslint global-require: 0 */
3
+ 'use strict';
4
+
5
+ const packageData = require('../package.json');
6
+ const fs = require('fs');
7
+ const pathlib = require('path');
8
+ const argv = require('minimist')(process.argv.slice(2));
9
+
10
+ function run() {
11
+ let cmd = ((argv._ && argv._[0]) || '').toLowerCase();
12
+ if (!cmd) {
13
+ if (argv.version || argv.v) {
14
+ cmd = 'version';
15
+ }
16
+
17
+ if (argv.help || argv.h) {
18
+ cmd = 'help';
19
+ }
20
+ }
21
+
22
+ switch (cmd) {
23
+ case 'help':
24
+ // Show version
25
+ fs.readFile(pathlib.join(__dirname, '..', 'help.txt'), (err, helpText) => {
26
+ if (err) {
27
+ console.error('Failed to load help information');
28
+ console.error(err);
29
+ return process.exit(1);
30
+ }
31
+ console.error(helpText.toString().trim());
32
+ console.error('');
33
+ process.exit();
34
+ });
35
+ break;
36
+
37
+ case 'version':
38
+ // Show version
39
+ console.log(`EmailEngine v${packageData.version} (${packageData.license})`);
40
+ return process.exit();
41
+
42
+ default:
43
+ // run normally
44
+ require('../server');
45
+ break;
46
+ }
47
+ }
48
+
49
+ run();
@@ -1,143 +1,143 @@
1
1
 
2
2
  [log]
3
- level = "trace"
3
+ level = "trace"
4
4
 
5
5
  [dbs]
6
6
 
7
- # By default all redis commands are sent against the same instance
8
- redis = "redis://127.0.0.1:6379/2"
7
+ # By default all redis commands are sent against the same instance
8
+ redis = "redis://127.0.0.1:6379/2"
9
9
 
10
- # Alternatively you can separate write and read tasks
11
- # by writing to master and reading from a closer replica
10
+ # Alternatively you can separate write and read tasks
11
+ # by writing to master and reading from a closer replica
12
12
 
13
- # Redis master
14
- #redisRead = "redis://127.0.0.1:6379/2"
13
+ # Redis master
14
+ #redisRead = "redis://127.0.0.1:6379/2"
15
15
 
16
- # Redis replica, preferrably localhost for fastest responses
17
- #redisWrite = "redis://127.0.0.1:6379/2"
16
+ # Redis replica, preferrably localhost for fastest responses
17
+ #redisWrite = "redis://127.0.0.1:6379/2"
18
18
 
19
19
  [api]
20
- # If enabled=false then API server is not started and configuration is not used
21
- enabled = true
22
- workers = 2
20
+ # If enabled=false then API server is not started and configuration is not used
21
+ enabled = true
22
+ workers = 1
23
23
 
24
- # You want to keep this local or firewalled otherwise anyone would be able to change DNS records
25
- # Do not use ports 80 or 443 as these are needed for the redirect interface
26
- port = 5080
27
- host = "127.0.0.1"
24
+ # You want to keep this local or firewalled otherwise anyone would be able to change DNS records
25
+ # Do not use ports 80 or 443 as these are needed for the redirect interface
26
+ port = 5080
27
+ host = "127.0.0.1"
28
28
 
29
29
  [dns]
30
- # If enabled=false then DNS server is not started and configuration is not used
31
- enabled = true
32
- workers = 2
30
+ # If enabled=false then DNS server is not started and configuration is not used
31
+ enabled = true
32
+ workers = 2
33
33
 
34
- # Default TTL value for all records
35
- ttl = 300 # 5 min
34
+ # Default TTL value for all records
35
+ ttl = 300 # 5 min
36
36
 
37
- # Use 53 on production.
38
- # This port is used both for TCP and UDP so make sure both are allowed by the firewall
39
- # ufw allow 53/tcp
40
- # ufw allow 53/udp
41
- port = 5053
37
+ # Use 53 on production.
38
+ # This port is used both for TCP and UDP so make sure both are allowed by the firewall
39
+ # ufw allow 53/tcp
40
+ # ufw allow 53/udp
41
+ port = 5053
42
42
 
43
- # In most cases you have to set actual interface IP address here
44
- # instead of using 0.0.0.0 as there might be already some other DNS
45
- # handlers running (eg. SystemD stub resolver) on some local address
46
- host = "127.0.0.1"
43
+ # In most cases you have to set actual interface IP address here
44
+ # instead of using 0.0.0.0 as there might be already some other DNS
45
+ # handlers running (eg. SystemD stub resolver) on some local address
46
+ host = "127.0.0.1"
47
47
 
48
48
  # List of Name Servers running this system
49
49
  # 1) ACME certificates are created only for domains that have NS records set to these values
50
50
  # 2) These values are reported as NS records for all domains
51
51
  [[ns]]
52
- # First NS in the list is also reported as the master in SOA record
53
- domain = "testdns01.pendingdns.com"
54
- ip = "188.165.168.22"
52
+ # First NS in the list is also reported as the master in SOA record
53
+ domain = "testdns01.pendingdns.com"
54
+ ip = "188.165.168.22"
55
55
  [[ns]]
56
- domain = "testdns02.pendingdns.com"
57
- ip = "51.38.177.242"
56
+ domain = "testdns02.pendingdns.com"
57
+ ip = "51.38.177.242"
58
58
 
59
59
  # SOA info
60
60
  # 1) This is reported as the SOA record for all domains
61
61
  [soa]
62
- admin = "hostmaster.pendingdns.com"
63
- serial = 2020050501
64
- refresh = 3600
65
- retry = 600
66
- expiration = 604800
67
- minimum = 60
62
+ admin = "hostmaster.pendingdns.com"
63
+ serial = 2020050501
64
+ refresh = 3600
65
+ retry = 600
66
+ expiration = 604800
67
+ minimum = 60
68
68
 
69
69
  # Resolver for external DNS queries, set ns=false to use system default
70
70
  # Mostly used for ANAME resolving
71
71
  [resolver]
72
- ns = ["8.8.8.8", "1.1.1.1"]
72
+ ns = ["8.8.8.8", "1.1.1.1"]
73
73
 
74
74
  # Settings for Let's Encrypt certificate generation
75
75
  [acme]
76
- # Local identifier for the ACME account
77
- key = "staging"
78
- # Defaults to Let's Encrypt staging environment
79
- directoryUrl = "https://acme-staging-v02.api.letsencrypt.org/directory"
80
-
81
- #key = "production"
82
- #directoryUrl = "https://acme-v02.api.letsencrypt.org/directory"
83
-
84
- # Email address to recive account related notifications
85
- # This value must be set as this is the person who agrees to LE TOS
86
- #email = "hostmaster@example.com"
87
- email = ""
76
+ # Local identifier for the ACME account
77
+ key = "staging"
78
+ # Defaults to Let's Encrypt staging environment
79
+ directoryUrl = "https://acme-staging-v02.api.letsencrypt.org/directory"
80
+
81
+ #key = "production"
82
+ #directoryUrl = "https://acme-v02.api.letsencrypt.org/directory"
83
+
84
+ # Email address to recive account related notifications
85
+ # This value must be set as this is the person who agrees to LE TOS
86
+ #email = "hostmaster@example.com"
87
+ email = ""
88
88
 
89
89
  [public]
90
- # If enabled=false then URL redirect server is not started and configuration is not used
91
- enabled = true
92
- server = "PendingDNS/1.0"
93
- workers = 2
94
-
95
- # path to error files, you can use your own error pages instead of the default ones
96
- # make sure though that the service user is able to read these
97
- # 1) All paths are relative to working directory, eg. /opt/pending-dns
98
- [public.errors]
99
- error404 = "./views/errors/404.hbs"
100
- error500 = "./views/errors/500.hbs"
101
-
102
- [public.http]
103
- # URL record handling over HTTP
104
- # Set to 80 in production
105
- port = 6080
106
- host = "0.0.0.0"
107
-
108
- [public.https]
109
- # URL record handling over HTTPS/HTTP2
110
- # Set to 443 in production
111
- port = 6443
112
- host = "0.0.0.0"
113
-
114
- # Path to default certificate files
115
- # These are used only for unknown domains, so can leave as is to use self-signed certs
116
- #key = "/path/to/default-privkey.pem"
117
- #cert = "/path/to/default-cert.pem"
118
-
119
- # Path to dhparam file
120
- # Generate using: openssl dhparam -out /path/to/dhparam.pem 4096
121
- #dhParam = "/path/to/dhparam.pem"
122
-
123
- # Allowed ciphers list. Leave empty for Node.js default set of ciphers
124
- ciphers = "ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384"
125
-
126
- # List redirect server IP addresses here
127
- # These are returned as A/AAAA query responses for the URL domain
128
- # It should include the IP addresses for all servers where you have PendingDNS installed and "public.enabled=true"
129
- [public.hosts]
130
- A = ["127.0.0.1", "127.0.0.2"]
131
- AAAA = []
90
+ # If enabled=false then URL redirect server is not started and configuration is not used
91
+ enabled = true
92
+ server = "PendingDNS/1.0"
93
+ workers = 2
94
+
95
+ # path to error files, you can use your own error pages instead of the default ones
96
+ # make sure though that the service user is able to read these
97
+ # 1) All paths are relative to working directory, eg. /opt/pending-dns
98
+ [public.errors]
99
+ error404 = "./views/errors/404.hbs"
100
+ error500 = "./views/errors/500.hbs"
101
+
102
+ [public.http]
103
+ # URL record handling over HTTP
104
+ # Set to 80 in production
105
+ port = 6080
106
+ host = "0.0.0.0"
107
+
108
+ [public.https]
109
+ # URL record handling over HTTPS/HTTP2
110
+ # Set to 443 in production
111
+ port = 6443
112
+ host = "0.0.0.0"
113
+
114
+ # Path to default certificate files
115
+ # These are used only for unknown domains, so can leave as is to use self-signed certs
116
+ #key = "/path/to/default-privkey.pem"
117
+ #cert = "/path/to/default-cert.pem"
118
+
119
+ # Path to dhparam file
120
+ # Generate using: openssl dhparam -out /path/to/dhparam.pem 4096
121
+ #dhParam = "/path/to/dhparam.pem"
122
+
123
+ # Allowed ciphers list. Leave empty for Node.js default set of ciphers
124
+ ciphers = "ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384"
125
+
126
+ # List redirect server IP addresses here
127
+ # These are returned as A/AAAA query responses for the URL domain
128
+ # It should include the IP addresses for all servers where you have PendingDNS installed and "public.enabled=true"
129
+ [public.hosts]
130
+ A = ["127.0.0.1", "127.0.0.2"]
131
+ AAAA = []
132
132
 
133
133
  [process]
134
- # Change user for child processes once privileged ports have been bound
135
- #user="www-data"
136
- #group="www-data"
134
+ # Change user for child processes once privileged ports have been bound
135
+ #user="www-data"
136
+ #group="www-data"
137
137
 
138
138
  [health]
139
- enabled = true # If enabled=false then health checks are not performed
140
- workers = 1
141
- handlers = 1 # How many health checks to run in parallel
142
- ttl = 30000 # Time in milliseconds until pending health check is considered failing
143
- delay = 60000 # Time in milliseconds between health checks against same target
139
+ enabled = true # If enabled=false then health checks are not performed
140
+ workers = 1
141
+ handlers = 1 # How many health checks to run in parallel
142
+ ttl = 30000 # Time in milliseconds until pending health check is considered failing
143
+ delay = 60000 # Time in milliseconds between health checks against same target
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>com.apple.security.cs.allow-jit</key>
6
+ <true/>
7
+ <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
8
+ <true/>
9
+ <key>com.apple.security.cs.allow-dyld-environment-variables</key>
10
+ <true/>
11
+ <key>com.apple.security.cs.disable-library-validation</key>
12
+ <true/>
13
+ <key>com.apple.security.network.client</key>
14
+ <true/>
15
+ <key>com.apple.security.network.server</key>
16
+ <true/>
17
+ </dict>
18
+ </plist>
package/help.txt ADDED
@@ -0,0 +1,23 @@
1
+ pending-dns [command] [options]
2
+
3
+ Lightweight API driven Authoritative DNS server.
4
+
5
+ Commands:
6
+ pending-dns Run the application
7
+ pending-dns help Show this information
8
+
9
+ Options:
10
+ -h, --help Show help
11
+
12
+ General options:
13
+ --dbs.redis Database connection URL [string]
14
+ --log.level Log level [string] [default: "trace"]
15
+
16
+ API options:
17
+ --api.host Host to bind to [string] [default: "127.0.0.1"]
18
+ --api.port Port to bind to [number] [default: 5080]
19
+
20
+ DNS options:
21
+ --dns.host Host to bind to [string] [default: "127.0.0.1"]
22
+ --dns.port Port to bind to [number] [default: 5053]
23
+
@@ -46,7 +46,9 @@ class DNSTcpServer extends EventEmitter {
46
46
  } catch (err) {
47
47
  // ignore
48
48
  }
49
+ return;
49
50
  }
51
+
50
52
  request.source = {
51
53
  type: 'tcp',
52
54
  port: socket.remotePort,
@@ -27,7 +27,9 @@ class DNSUdpServer extends EventEmitter {
27
27
  request = Packet.parse(buffer);
28
28
  } catch (err) {
29
29
  logger.error({ msg: 'Failed to parse DNS package', type: 'udp', err, buffer, port: rinfo.port, address: rinfo.address });
30
+ return;
30
31
  }
32
+
31
33
  request.source = {
32
34
  type: 'udp',
33
35
  port: rinfo.port,
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "pending-dns",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Lightweight API driven DNS server",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "start": "node server.js",
8
8
  "test": "grunt",
9
- "licenses": "npm-license-crawler --production --csv ./licenses.csv"
9
+ "build-source": "rm -rf node_modules package-lock.json && npm install && npm run licenses && rm -rf node_modules package-lock.json && npm install --production && rm -rf package-lock.json",
10
+ "build-dist-fast": "npx pkg --debug package.json && rm -rf package-lock.json && npm install",
11
+ "build-dist": "npx pkg --compress Brotli package.json && rm -rf package-lock.json && npm install",
12
+ "licenses": "license-report --only=prod --output=table --config license-report-config.json > licenses.txt"
10
13
  },
11
14
  "repository": {
12
15
  "type": "git",
@@ -25,36 +28,56 @@
25
28
  },
26
29
  "homepage": "https://github.com/postalsys/pending-dns#readme",
27
30
  "devDependencies": {
28
- "eslint": "8.18.0",
31
+ "eslint": "8.47.0",
29
32
  "eslint-config-nodemailer": "1.2.0",
30
- "eslint-config-prettier": "8.5.0",
31
- "grunt": "1.5.3",
33
+ "eslint-config-prettier": "9.0.0",
34
+ "grunt": "1.6.1",
32
35
  "grunt-cli": "1.4.3",
33
- "grunt-eslint": "24.0.0",
34
- "npm-license-crawler": "0.2.1"
36
+ "grunt-eslint": "24.3.0",
37
+ "license-report": "6.4.0"
35
38
  },
36
39
  "dependencies": {
40
+ "@bugsnag/js": "7.21.0",
37
41
  "@fidm/x509": "1.2.1",
38
- "@hapi/boom": "10.0.0",
39
- "@hapi/hapi": "20.2.2",
40
- "@hapi/inert": "6.0.5",
42
+ "@hapi/boom": "10.0.1",
43
+ "@hapi/hapi": "21.3.2",
44
+ "@hapi/inert": "7.1.0",
41
45
  "@hapi/joi": "17.1.1",
42
- "@hapi/vision": "6.1.0",
46
+ "@hapi/vision": "7.0.3",
43
47
  "@root/acme": "3.1.0",
44
48
  "@root/csr": "0.8.1",
45
- "dns2": "2.0.2",
46
- "hapi-pino": "10.1.0",
47
- "hapi-swagger": "14.5.5",
49
+ "dns2": "2.1.0",
50
+ "handlebars": "4.7.8",
51
+ "hapi-pino": "12.1.0",
52
+ "hapi-swagger": "17.1.0",
48
53
  "http-proxy": "1.18.1",
49
- "ioredfour": "1.2.0-ioredis-06",
50
- "ioredis": "5.0.6",
51
- "ipaddr.js": "2.0.1",
54
+ "ioredfour": "1.2.0-ioredis-07",
55
+ "ioredis": "5.3.2",
56
+ "ipaddr.js": "2.1.0",
57
+ "minimist": "1.2.8",
52
58
  "node-rsa": "1.1.1",
53
59
  "pem-jwk": "2.0.0",
54
- "pino": "8.1.0",
55
- "punycode": "^2.1.1",
60
+ "pino": "8.15.0",
61
+ "punycode": "2.3.0",
56
62
  "shortid": "2.2.16",
57
- "uuid": "^8.3.2",
58
- "wild-config": "1.6.1"
63
+ "uuid": "9.0.0",
64
+ "wild-config": "1.7.0"
65
+ },
66
+ "bin": {
67
+ "pending-dns": "bin/pending-dns.js"
68
+ },
69
+ "pkg": {
70
+ "assets": [
71
+ "licenses.txt",
72
+ "LICENSE.txt",
73
+ "help.txt"
74
+ ],
75
+ "targets": [
76
+ "node18-linux-x64",
77
+ "node18-macos-x64",
78
+ "node18-macos-arm64",
79
+ "node18-win-x64"
80
+ ],
81
+ "outputPath": "ee-dist"
59
82
  }
60
83
  }
package/server.js CHANGED
@@ -7,6 +7,7 @@ const argv = process.argv.slice(2);
7
7
  const config = require('wild-config');
8
8
  const logger = require('./lib/logger').child({ component: 'server' });
9
9
  const pathlib = require('path');
10
+ const packageData = require('./package.json');
10
11
  const { Worker, SHARE_ENV } = require('worker_threads');
11
12
  const { isemail } = require('./lib/tools');
12
13
 
@@ -15,6 +16,29 @@ if (!config.acme || !isemail(config.acme.email)) {
15
16
  process.exit(51);
16
17
  }
17
18
 
19
+ const Bugsnag = require('@bugsnag/js');
20
+ if (process.env.BUGSNAG_API_KEY) {
21
+ Bugsnag.start({
22
+ apiKey: process.env.BUGSNAG_API_KEY,
23
+ appVersion: packageData.version,
24
+ logger: {
25
+ debug(...args) {
26
+ logger.debug({ msg: args.shift(), worker: 'main', source: 'bugsnag', args: args.length ? args : undefined });
27
+ },
28
+ info(...args) {
29
+ logger.debug({ msg: args.shift(), worker: 'main', source: 'bugsnag', args: args.length ? args : undefined });
30
+ },
31
+ warn(...args) {
32
+ logger.warn({ msg: args.shift(), worker: 'main', source: 'bugsnag', args: args.length ? args : undefined });
33
+ },
34
+ error(...args) {
35
+ logger.error({ msg: args.shift(), worker: 'main', source: 'bugsnag', args: args.length ? args : undefined });
36
+ }
37
+ }
38
+ });
39
+ logger.notifyError = Bugsnag.notify.bind(Bugsnag);
40
+ }
41
+
18
42
  let closing = false;
19
43
 
20
44
  let workers = new Map();
@@ -67,17 +91,30 @@ if (config.health.enabled) {
67
91
  spawnWorker('health');
68
92
  }
69
93
 
70
- const closeProcess = code => {
94
+ const closeProcess = (code, errType, err) => {
71
95
  if (closing) {
72
96
  return;
73
97
  }
74
98
  closing = true;
75
- setTimeout(() => {
76
- process.exit(code);
77
- }, 10);
99
+
100
+ if (!code) {
101
+ return setTimeout(() => {
102
+ process.exit(code);
103
+ }, 10);
104
+ }
105
+
106
+ logger.fatal({
107
+ msg: errType,
108
+ _msg: errType,
109
+ err
110
+ });
111
+
112
+ if (!logger.notifyError) {
113
+ setTimeout(() => process.exit(code), 10);
114
+ }
78
115
  };
79
116
 
80
- process.on('uncaughtException', () => closeProcess(1));
81
- process.on('unhandledRejection', () => closeProcess(2));
117
+ process.on('uncaughtException', err => closeProcess(1, 'uncaughtException', err));
118
+ process.on('unhandledRejection', err => closeProcess(2, 'unhandledRejection', err));
82
119
  process.on('SIGTERM', () => closeProcess(0));
83
120
  process.on('SIGINT', () => closeProcess(0));
package/workers/api.js CHANGED
@@ -9,18 +9,31 @@ const config = require('wild-config');
9
9
  const workerName = 'api';
10
10
 
11
11
  let closing = false;
12
- const closeProcess = code => {
12
+ const closeProcess = (code, errType, err) => {
13
13
  if (closing) {
14
14
  return;
15
15
  }
16
16
  closing = true;
17
- setTimeout(() => {
18
- process.exit(code);
19
- }, 10);
17
+
18
+ if (!code) {
19
+ return setTimeout(() => {
20
+ process.exit(code);
21
+ }, 10);
22
+ }
23
+
24
+ logger.fatal({
25
+ msg: errType,
26
+ _msg: errType,
27
+ err
28
+ });
29
+
30
+ if (!logger.notifyError) {
31
+ setTimeout(() => process.exit(code), 10);
32
+ }
20
33
  };
21
34
 
22
- process.on('uncaughtException', () => closeProcess(1));
23
- process.on('unhandledRejection', () => closeProcess(2));
35
+ process.on('uncaughtException', err => closeProcess(1, 'uncaughtException', err));
36
+ process.on('unhandledRejection', err => closeProcess(2, 'unhandledRejection', err));
24
37
  process.on('SIGTERM', () => closeProcess(0));
25
38
  process.on('SIGINT', () => closeProcess(0));
26
39
 
package/workers/dns.js CHANGED
@@ -9,21 +9,58 @@ const config = require('wild-config');
9
9
  const workerName = 'dns';
10
10
 
11
11
  let closing = false;
12
- const closeProcess = code => {
12
+ const closeProcess = (code, errType, err) => {
13
13
  if (closing) {
14
14
  return;
15
15
  }
16
16
  closing = true;
17
- setTimeout(() => {
18
- process.exit(code);
19
- }, 10);
17
+
18
+ if (!code) {
19
+ return setTimeout(() => {
20
+ process.exit(code);
21
+ }, 10);
22
+ }
23
+
24
+ logger.fatal({
25
+ msg: errType,
26
+ _msg: errType,
27
+ err
28
+ });
29
+
30
+ if (!logger.notifyError) {
31
+ setTimeout(() => process.exit(code), 10);
32
+ }
20
33
  };
21
34
 
22
- process.on('uncaughtException', () => closeProcess(1));
23
- process.on('unhandledRejection', () => closeProcess(2));
35
+ process.on('uncaughtException', err => closeProcess(1, 'uncaughtException', err));
36
+ process.on('unhandledRejection', err => closeProcess(2, 'unhandledRejection', err));
24
37
  process.on('SIGTERM', () => closeProcess(0));
25
38
  process.on('SIGINT', () => closeProcess(0));
26
39
 
40
+ const packageData = require('../package.json');
41
+ const Bugsnag = require('@bugsnag/js');
42
+ if (process.env.BUGSNAG_API_KEY) {
43
+ Bugsnag.start({
44
+ apiKey: process.env.BUGSNAG_API_KEY,
45
+ appVersion: packageData.version,
46
+ logger: {
47
+ debug(...args) {
48
+ logger.debug({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
49
+ },
50
+ info(...args) {
51
+ logger.debug({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
52
+ },
53
+ warn(...args) {
54
+ logger.warn({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
55
+ },
56
+ error(...args) {
57
+ logger.error({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
58
+ }
59
+ }
60
+ });
61
+ logger.notifyError = Bugsnag.notify.bind(Bugsnag);
62
+ }
63
+
27
64
  const run = () => {
28
65
  require(`../lib/${workerName}-server.js`)()
29
66
  .then(() => {
package/workers/health.js CHANGED
@@ -9,21 +9,59 @@ const config = require('wild-config');
9
9
  const workerName = 'health';
10
10
 
11
11
  let closing = false;
12
- const closeProcess = code => {
12
+ const closeProcess = (code, errType, err) => {
13
13
  if (closing) {
14
14
  return;
15
15
  }
16
16
  closing = true;
17
- setTimeout(() => {
18
- process.exit(code);
19
- }, 10);
17
+
18
+ if (!code) {
19
+ return setTimeout(() => {
20
+ process.exit(code);
21
+ }, 10);
22
+ }
23
+
24
+ logger.fatal({
25
+ msg: errType,
26
+ _msg: errType,
27
+ err
28
+ });
29
+
30
+ if (!logger.notifyError) {
31
+ setTimeout(() => process.exit(code), 10);
32
+ }
20
33
  };
21
34
 
22
- process.on('uncaughtException', () => closeProcess(1));
23
- process.on('unhandledRejection', () => closeProcess(2));
35
+ process.on('uncaughtException', err => closeProcess(1, 'uncaughtException', err));
36
+ process.on('unhandledRejection', err => closeProcess(2, 'unhandledRejection', err));
24
37
  process.on('SIGTERM', () => closeProcess(0));
25
38
  process.on('SIGINT', () => closeProcess(0));
26
39
 
40
+ const packageData = require('../package.json');
41
+ const Bugsnag = require('@bugsnag/js');
42
+
43
+ if (process.env.BUGSNAG_API_KEY) {
44
+ Bugsnag.start({
45
+ apiKey: process.env.BUGSNAG_API_KEY,
46
+ appVersion: packageData.version,
47
+ logger: {
48
+ debug(...args) {
49
+ logger.debug({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
50
+ },
51
+ info(...args) {
52
+ logger.debug({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
53
+ },
54
+ warn(...args) {
55
+ logger.warn({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
56
+ },
57
+ error(...args) {
58
+ logger.error({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
59
+ }
60
+ }
61
+ });
62
+ logger.notifyError = Bugsnag.notify.bind(Bugsnag);
63
+ }
64
+
27
65
  const run = () => {
28
66
  require(`../lib/${workerName}-worker.js`)()
29
67
  .then(() => {
package/workers/public.js CHANGED
@@ -9,21 +9,58 @@ const config = require('wild-config');
9
9
  const workerName = 'public';
10
10
 
11
11
  let closing = false;
12
- const closeProcess = code => {
12
+ const closeProcess = (code, errType, err) => {
13
13
  if (closing) {
14
14
  return;
15
15
  }
16
16
  closing = true;
17
- setTimeout(() => {
18
- process.exit(code);
19
- }, 10);
17
+
18
+ if (!code) {
19
+ return setTimeout(() => {
20
+ process.exit(code);
21
+ }, 10);
22
+ }
23
+
24
+ logger.fatal({
25
+ msg: errType,
26
+ _msg: errType,
27
+ err
28
+ });
29
+
30
+ if (!logger.notifyError) {
31
+ setTimeout(() => process.exit(code), 10);
32
+ }
20
33
  };
21
34
 
22
- process.on('uncaughtException', () => closeProcess(1));
23
- process.on('unhandledRejection', () => closeProcess(2));
35
+ process.on('uncaughtException', err => closeProcess(1, 'uncaughtException', err));
36
+ process.on('unhandledRejection', err => closeProcess(2, 'unhandledRejection', err));
24
37
  process.on('SIGTERM', () => closeProcess(0));
25
38
  process.on('SIGINT', () => closeProcess(0));
26
39
 
40
+ const packageData = require('../package.json');
41
+ const Bugsnag = require('@bugsnag/js');
42
+ if (process.env.BUGSNAG_API_KEY) {
43
+ Bugsnag.start({
44
+ apiKey: process.env.BUGSNAG_API_KEY,
45
+ appVersion: packageData.version,
46
+ logger: {
47
+ debug(...args) {
48
+ logger.debug({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
49
+ },
50
+ info(...args) {
51
+ logger.debug({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
52
+ },
53
+ warn(...args) {
54
+ logger.warn({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
55
+ },
56
+ error(...args) {
57
+ logger.error({ msg: args.shift(), worker: workerName, source: 'bugsnag', args: args.length ? args : undefined });
58
+ }
59
+ }
60
+ });
61
+ logger.notifyError = Bugsnag.notify.bind(Bugsnag);
62
+ }
63
+
27
64
  const run = () => {
28
65
  require(`../lib/${workerName}-server.js`)()
29
66
  .then(() => {