@nxtedition/lib 16.0.12 → 17.0.1

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.
Files changed (3) hide show
  1. package/app.js +50 -37
  2. package/logger.js +3 -47
  3. package/package.json +1 -1
package/app.js CHANGED
@@ -3,7 +3,6 @@ import net from 'node:net'
3
3
  import stream from 'node:stream'
4
4
  import { Buffer } from 'node:buffer'
5
5
  import { getDockerSecretsSync } from './docker-secrets.js'
6
- import { getGlobalDispatcher } from 'undici'
7
6
  import fp from 'lodash/fp.js'
8
7
  import { isMainThread, parentPort } from 'node:worker_threads'
9
8
  import toobusy from 'toobusy-js'
@@ -116,57 +115,71 @@ export function makeApp(appConfig, onTerminate) {
116
115
  } (module:${serviceModule}; instance:${serviceInstanceId}) Node/${process.version}`) ??
117
116
  null)
118
117
 
119
- const terminate = async (finalLogger) => {
120
- finalLogger ??= logger
118
+ {
119
+ const loggerConfig = { ...appConfig.logger, ...config.logger }
120
+
121
+ process.on('uncaughtExceptionMonitor', (err) => {
122
+ logger.fatal({ err }, 'uncaught exception')
123
+ })
124
+
125
+ logger = createLogger({
126
+ ...loggerConfig,
127
+ name: serviceName,
128
+ module: serviceModule,
129
+ base: loggerConfig?.base ? { ...loggerConfig.base } : {},
130
+ })
131
+
132
+ destroyers.push(
133
+ () =>
134
+ new Promise((resolve, reject) =>
135
+ logger.flush((err) => (err ? reject(err) : resolve(null))),
136
+ ),
137
+ )
138
+ }
139
+
140
+ let terminated = false
141
+ const terminate = async () => {
142
+ if (terminated) {
143
+ return
144
+ }
145
+
146
+ terminated = true
121
147
 
122
148
  ac.abort()
123
149
 
124
- try {
125
- if (onTerminate) {
126
- try {
127
- await onTerminate(finalLogger)
128
- } catch (err) {
129
- finalLogger.error({ err }, 'terminate error')
130
- }
150
+ if (onTerminate) {
151
+ try {
152
+ await onTerminate(logger)
153
+ } catch (err) {
154
+ logger.error({ err }, 'terminate error')
131
155
  }
156
+ }
132
157
 
133
- const dispatcher = getGlobalDispatcher()
134
- if (dispatcher?.close) {
135
- destroyers.push(async () => {
136
- const timeout = setTimeout(() => {
137
- dispatcher.destroy()
138
- }, 4e3)
139
- await dispatcher.close()
140
- clearTimeout(timeout)
141
- })
158
+ for (const { reason } of await Promise.allSettled(
159
+ destroyers.filter(Boolean).map((fn) => fn(logger)),
160
+ )) {
161
+ if (reason) {
162
+ logger.error({ err: reason }, 'shutdown error')
142
163
  }
143
-
144
- await Promise.all(destroyers.filter(Boolean).map((fn) => fn(finalLogger)))
145
- } catch (err) {
146
- finalLogger.error({ err }, 'shutdown error')
147
164
  }
148
- }
149
165
 
150
- {
151
- const loggerConfig = { ...appConfig.logger, ...config.logger }
152
-
153
- logger = createLogger(
154
- {
155
- ...loggerConfig,
156
- name: serviceName,
157
- module: serviceModule,
158
- base: loggerConfig?.base ? { ...loggerConfig.base } : {},
159
- },
160
- terminate,
161
- )
166
+ setTimeout(() => {
167
+ process.abort()
168
+ }, 10e3).unref()
162
169
  }
163
170
 
171
+ process
172
+ .on('beforeExit', terminate)
173
+ .on('SIGINT', terminate)
174
+ .on('SIGTERM', terminate)
175
+ .on('uncaughtExceptionMonitor', terminate)
176
+
164
177
  logger.debug({ data: JSON.stringify(config, null, 2) }, 'config')
165
178
 
166
179
  if (!isMainThread && parentPort) {
167
180
  parentPort.on('message', ({ type }) => {
168
181
  if (type === 'nxt:worker:terminate') {
169
- terminate(null)
182
+ terminate()
170
183
  }
171
184
  })
172
185
  }
package/logger.js CHANGED
@@ -1,9 +1,7 @@
1
- import fs from 'node:fs'
2
- import util from 'node:util'
1
+ import assert from 'node:assert'
3
2
  import { isMainThread } from 'node:worker_threads'
4
3
  import serializers from './serializers.js'
5
4
  import pino from 'pino'
6
- import xuid from 'xuid'
7
5
 
8
6
  const isProduction = process.env.NODE_ENV === 'production'
9
7
 
@@ -11,6 +9,8 @@ export function createLogger(
11
9
  { level = isProduction ? 'debug' : 'trace', flushInterval = 1e3, stream = null, ...options } = {},
12
10
  onTerminate,
13
11
  ) {
12
+ assert(!onTerminate)
13
+
14
14
  if (!stream) {
15
15
  if (
16
16
  process.stdout.write !== process.stdout.constructor.prototype.write ||
@@ -55,49 +55,5 @@ export function createLogger(
55
55
  stream,
56
56
  )
57
57
 
58
- let called = false
59
- const finalHandler = async (err, evt) => {
60
- if (called) {
61
- return
62
- }
63
- called = true
64
-
65
- try {
66
- fs.writeFileSync(`/tmp/${new Date()}-${xuid()}`, util.inspect(err), 'utf8')
67
- } catch {
68
- // Do nothing...
69
- }
70
-
71
- if (err) {
72
- if (!(err instanceof Error)) {
73
- err = new Error(err)
74
- }
75
- logger.fatal({ err }, evt || 'error caused exit')
76
-
77
- logger.flush()
78
- } else {
79
- logger.info(`${evt} caught`)
80
-
81
- let exitSignal
82
- try {
83
- exitSignal = onTerminate ? await onTerminate(logger) : null
84
- } catch (err) {
85
- exitSignal = err.exitSignal || 1
86
- logger.warn({ err })
87
- }
88
-
89
- logger.info({ exitSignal }, 'exit')
90
-
91
- logger.flush()
92
- }
93
- }
94
-
95
- process.on('exit', () => finalHandler(null, 'exit'))
96
- process.on('beforeExit', () => finalHandler(null, 'beforeExit'))
97
- process.on('SIGINT', () => finalHandler(null, 'SIGINT'))
98
- process.on('SIGQUIT', () => finalHandler(null, 'SIGQUIT'))
99
- process.on('SIGTERM', () => finalHandler(null, 'SIGTERM'))
100
- process.on('uncaughtException', (err, origin) => finalHandler(err, origin))
101
-
102
58
  return logger
103
59
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/lib",
3
- "version": "16.0.12",
3
+ "version": "17.0.1",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "type": "module",