@superhero/core 4.0.0-beta.6 → 4.0.0-beta.8

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.
package/README.md CHANGED
@@ -44,10 +44,9 @@ await core.bootstrap()
44
44
 
45
45
  // Locate a service
46
46
  const myService = core.locate('myService')
47
- console.log(myService)
48
47
 
49
48
  // Graceful shutdown
50
- await core.destruct()
49
+ await core.destroy()
51
50
  ```
52
51
 
53
52
  ### Clustering Example
@@ -66,8 +65,8 @@ await core.add('./path/to/config.js')
66
65
  // Bootstrap core
67
66
  await core.bootstrap()
68
67
 
69
- // Destruct core when done
70
- await core.destruct()
68
+ // Destroy core when done
69
+ await core.destroy()
71
70
  ```
72
71
 
73
72
  ---
@@ -157,7 +156,7 @@ new Core(branch: string = undefined)
157
156
  - **`cluster(forks: number, branch?: number, version?: number): Promise<number>`**
158
157
  Start clustering with the specified number of workers.
159
158
 
160
- - **`destruct(): Promise<void>`**
159
+ - **`destroy(): Promise<void>`**
161
160
  Gracefully shutdown the core, its workers, and services.
162
161
 
163
162
  #### Properties
package/index.js CHANGED
@@ -5,6 +5,7 @@ import path from 'node:path'
5
5
  import bootstrap from '@superhero/bootstrap'
6
6
  import Config from '@superhero/config'
7
7
  import Locate from '@superhero/locator'
8
+ import Log from '@superhero/log'
8
9
 
9
10
  export default class Core
10
11
  {
@@ -19,7 +20,7 @@ export default class Core
19
20
  this.branch = branch
20
21
  this.basePath = this.locate.pathResolver.basePath // synchronize the base path.
21
22
  this.locate.set('@superhero/config', this.config)
22
- Core.#setupDestructor(this)
23
+ Core.#setupDestroyer(this)
23
24
  }
24
25
 
25
26
  #branch
@@ -31,7 +32,7 @@ export default class Core
31
32
  {
32
33
  get: (target, prop, receiver) =>
33
34
  {
34
- // when pushing events to the eventlog, also send the events to all workers
35
+ // when pushing events to the eventlog, also sync the event to all workers
35
36
  if('push' === prop) return (...events) =>
36
37
  {
37
38
  setImmediate(() =>
@@ -48,79 +49,84 @@ export default class Core
48
49
  }
49
50
  })
50
51
 
52
+ // An exposed log instance taht the core instance uses that is open for modification.
53
+ static log = new Log({ label: process.env.CORE_CLUSTER_WORKER ? `[CORE:${process.env.CORE_CLUSTER_WORKER}]` : '[CORE]' })
54
+
51
55
  // Used for graceful termination, if multiple cores are instanciated.
52
56
  static #cores = new Map
53
57
 
54
58
  // Used to prevent multiple observers on the process events.
55
- static #destructorIsSetup = false
59
+ static #destroyerIsSetup = false
56
60
 
57
- // Used to prevent multiple destruct calls.
58
- static #destructorIsTriggered = false
61
+ // Used to prevent multiple destroy calls.
62
+ static #destroyerIsTriggered = false
59
63
 
60
- static #setupDestructor(core)
64
+ static #setupDestroyer(core)
61
65
  {
62
66
  Core.#cores.set(core, core)
63
67
 
64
- if(false === Core.#destructorIsSetup)
68
+ if(false === Core.#destroyerIsSetup)
65
69
  {
66
- Core.#destructorIsSetup = true
70
+ Core.#destroyerIsSetup = true
67
71
 
68
- process.on('SIGINT', (signal) => Core.#destructor(signal))
69
- process.on('SIGTERM', (signal) => Core.#destructor(signal))
72
+ process.on('SIGINT', (signal) => Core.#destroy(signal))
73
+ process.on('SIGTERM', (signal) => Core.#destroy(signal))
70
74
 
71
- process.on('unhandledRejection', (reason) => Core.#destructor(false, reason))
72
- process.on('uncaughtException', (error) => Core.#destructor(false, error))
75
+ process.on('unhandledRejection', (reason) => Core.#destroy(false, reason))
76
+ process.on('uncaughtException', (error) => Core.#destroy(false, error))
73
77
  }
74
78
  }
75
79
 
76
80
  /**
77
- * Attempts to destruct all core instances gracefully.
81
+ * Attempts to destroy all core instances gracefully.
78
82
  */
79
- static async #destructor(signal, reason)
83
+ static async #destroy(signal, reason)
80
84
  {
81
- if(Core.#destructorIsTriggered)
85
+ if(Core.#destroyerIsTriggered)
82
86
  {
83
87
  Core.log.info`redundant shutdown signal ${signal} waiting for previous shutdown process to finalize…`
84
- reason && Core.log.error(reason)
88
+ reason && Core.log.fail`${reason}`
85
89
  return
86
90
  }
87
91
 
88
- Core.#destructorIsTriggered = true
92
+ Core.#destroyerIsTriggered = true
89
93
 
90
- signal && Core.log.info`${signal} ⇢ graceful shutdown initiated…`
94
+ signal
95
+ ? Core.log.info`graceful shutdown initiated ${signal}`
96
+ : Core.log.info`graceful shutdown initiated`
91
97
 
92
98
  const
93
- destructCores = [],
94
- destructRejects = []
99
+ destroyedCores = [],
100
+ destroyRejects = []
95
101
 
96
102
  for(const core of Core.#cores.values())
97
103
  {
98
- destructCores.push((async () =>
104
+ destroyedCores.push((async () =>
99
105
  {
100
106
  try
101
107
  {
102
- await core.destruct()
108
+ await core.destroy()
103
109
  }
104
110
  catch(error)
105
111
  {
106
- destructRejects.push(error)
112
+ destroyRejects.push(error)
107
113
  }
108
114
  })())
109
115
  }
110
116
 
111
- await Promise.all(destructCores)
117
+ await Promise.all(destroyedCores)
112
118
 
113
- if(destructRejects.length)
119
+ if(destroyRejects.length)
114
120
  {
115
121
  const error = new Error('Failed to shutdown gracefully')
116
- error.code = 'E_CORE_DESTRUCT_GRACEFUL'
117
- error.cause = destructRejects
118
- Core.log.error(error)
122
+ error.code = 'E_CORE_DESTROY_GRACEFUL'
123
+ error.cause = destroyRejects
124
+ Core.log.fail`${error}`
119
125
  setImmediate(() => process.exit(1))
120
126
  }
121
127
  else if(reason)
122
128
  {
123
- Core.log.error(reason)
129
+ Core.log.fail`${reason}`
124
130
  setImmediate(() => process.exit(1))
125
131
  }
126
132
  else
@@ -129,25 +135,25 @@ export default class Core
129
135
  }
130
136
  }
131
137
 
132
- async destruct()
138
+ async destroy()
133
139
  {
134
140
  // First remove the core instance from the static core registry
135
- // to prevent multiple destruct calls.
141
+ // to prevent multiple destroy calls.
136
142
  Core.#cores.delete(this)
137
143
 
138
- // Then destruct the core workers, if clustered, using a timeout.
144
+ // Then destroy the core workers, if clustered, using a timeout.
139
145
  const
140
- timeout = this.config.find('core/destruct/timeout', 15e3),
141
- timeoutError = new Error(`Failed to destruct core within ${(timeout/1e3).toFixed(1)}s`),
142
- destructTimeout = (ctx) => new Promise((_, reject) => ctx.id = setTimeout(() => reject(timeoutError), timeout)),
143
- destructWorkers = [],
144
- destructRejects = []
146
+ timeout = this.config.find('core/destroy/timeout', 15e3),
147
+ timeoutError = new Error(`Failed to destroy core within ${(timeout/1e3).toFixed(1)}s`),
148
+ destroyTimeout = (ctx) => new Promise((_, reject) => ctx.id = setTimeout(() => reject(timeoutError), timeout)),
149
+ destroyedWorkers = [],
150
+ destroyRejects = []
145
151
 
146
- timeoutError.code = 'E_CORE_DESTRUCT_TIMEOUT'
152
+ timeoutError.code = 'E_CORE_DESTROY_TIMEOUT'
147
153
 
148
154
  for(const id in this.#workers)
149
155
  {
150
- destructWorkers.push((async () =>
156
+ destroyedWorkers.push((async () =>
151
157
  {
152
158
  // Attempt to kill the worker.
153
159
  this.#workers[id].kill()
@@ -158,42 +164,42 @@ export default class Core
158
164
 
159
165
  try
160
166
  {
161
- if(destructWorkers.length)
167
+ if(destroyedWorkers.length)
162
168
  {
163
169
  const timeout = {}
164
- await Promise.race([ destructTimeout(timeout), Promise.all(destructWorkers) ])
170
+ await Promise.race([ destroyTimeout(timeout), Promise.all(destroyedWorkers) ])
165
171
  clearTimeout(timeout.id)
166
172
  }
167
173
  }
168
174
  catch(reason)
169
175
  {
170
- const error = new Error(`Failed to destruct workers`)
171
- error.code = 'E_CORE_DESTRUCT_WORKERS'
176
+ const error = new Error(`Failed to destroy workers`)
177
+ error.code = 'E_CORE_DESTROY_WORKERS'
172
178
  error.cause = reason
173
- destructRejects.push(error)
179
+ destroyRejects.push(error)
174
180
  }
175
181
 
176
- // Then destruct the core locator and all loaded services, restricted by a
182
+ // Then destroy the core locator and all loaded services, restricted by a
177
183
  // timeout if it takes to long.
178
184
  try
179
185
  {
180
186
  const timeout = {}
181
- await Promise.race([ destructTimeout(timeout), this.locate.destruct() ])
187
+ await Promise.race([ destroyTimeout(timeout), this.locate.destroy() ])
182
188
  clearTimeout(timeout.id)
183
189
  }
184
190
  catch(reason)
185
191
  {
186
- const error = new Error(`Failed to destruct locator`)
187
- error.code = 'E_CORE_DESTRUCT_LOCATOR'
192
+ const error = new Error(`Failed to destroy locator`)
193
+ error.code = 'E_CORE_DESTROY_LOCATOR'
188
194
  error.cause = reason
189
- destructRejects.push(error)
195
+ destroyRejects.push(error)
190
196
  }
191
197
 
192
- if(destructRejects.length)
198
+ if(destroyRejects.length)
193
199
  {
194
- const error = new Error(`Failed to destruct core gracefully`)
195
- error.code = 'E_CORE_DESTRUCT'
196
- error.cause = destructRejects
200
+ const error = new Error(`Failed to destroy core gracefully`)
201
+ error.code = 'E_CORE_DESTROY'
202
+ error.cause = destroyRejects
197
203
  throw error
198
204
  }
199
205
  }
@@ -329,7 +335,7 @@ export default class Core
329
335
  this.#workers[forkId].once('exit', this.#reloadWorker.bind(this, forkId, forkBranch, forkVersion))
330
336
  this.#workers[forkId].sync = this.#createSynchoronizer(forkId)
331
337
 
332
- Core.log.info`clustered ${'CORE:' + forkId}`
338
+ Core.log.info`${'CORE:' + forkId} ⇡ clustered`
333
339
 
334
340
  try
335
341
  {
@@ -342,6 +348,8 @@ export default class Core
342
348
  error.cause = reason
343
349
  throw error
344
350
  }
351
+
352
+ Core.log.info`synchronized ${'CORE:' + forkId}`
345
353
  }
346
354
 
347
355
  return branch + forks
@@ -377,7 +385,7 @@ export default class Core
377
385
 
378
386
  if('string' === typeof absolutePath)
379
387
  {
380
- serviceMap[entry] = path.normalize(absolutePath + '/' + servicePath)
388
+ serviceMap[entry] = path.normalize(path.join(absolutePath, servicePath))
381
389
  }
382
390
  }
383
391
  }
@@ -634,7 +642,7 @@ export default class Core
634
642
 
635
643
  if('string' === typeof absolutePath)
636
644
  {
637
- dependencies[i] = path.normalize(absolutePath + '/' + dependency)
645
+ dependencies[i] = path.normalize(path.join(absolutePath, dependency))
638
646
  }
639
647
  }
640
648
  }
@@ -734,22 +742,4 @@ export default class Core
734
742
  throw error
735
743
  }
736
744
  }
737
-
738
- // Will make the log methods availible to overwrite
739
- // if a custom logging is desired.
740
- static log =
741
- {
742
- label : process.env.CORE_CLUSTER_WORKER
743
- ? `[CORE:${process.env.CORE_CLUSTER_WORKER}]`
744
- : '[CORE]',
745
- icon : ' ⇢ ',
746
- basic : (template, ...args) => template.reduce((result, part, i) => result + args[i - 1] + part),
747
- simple : (template, ...args) => this.log.label + this.log.icon + this.log.basic(template, ...args),
748
- colors : (template, ...args) => '\x1b[90m' + this.log.supress`${this.log.label + this.log.icon}` + template.reduce((result, part, i) => result + '\x1b[96m\x1b[2m' + args[i - 1] + '\x1b[90m' + part) + '\x1b[0m',
749
- supress : (template, ...args) => '\x1b[1m\x1b[2m' + this.log.basic(template, ...args) + '\x1b[22m',
750
- format : (...args) => this.log.colors(...args),
751
- info : (...args) => console.info (this.log.format(...args)),
752
- warning : (...args) => console.warn (this.log.format(...args)),
753
- error : (...args) => console.error (this.log.format`failure`, ...args)
754
- }
755
745
  }
package/index.test.js CHANGED
@@ -92,6 +92,6 @@ suite('@superhero/core', () =>
92
92
  core.bootstrap(),
93
93
  'Should bootstrap without errors')
94
94
 
95
- await core.destruct()
95
+ await core.destroy()
96
96
  })
97
97
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superhero/core",
3
- "version": "4.0.0-beta.6",
3
+ "version": "4.0.0-beta.8",
4
4
  "description": "Core functionalities for the superhero framework.",
5
5
  "main": "index.js",
6
6
  "license": "MIT",
@@ -11,7 +11,8 @@
11
11
  "dependencies": {
12
12
  "@superhero/bootstrap": "^4.1.0",
13
13
  "@superhero/config": "^4.1.2",
14
- "@superhero/locator": "^4.1.2"
14
+ "@superhero/locator": "^4.2.0",
15
+ "@superhero/log": "^4.0.0"
15
16
  },
16
17
  "scripts": {
17
18
  "test": "node --trace-warnings --test --experimental-test-coverage"