@nxtedition/lib 21.5.2 → 21.5.4

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 (4) hide show
  1. package/app.js +121 -60
  2. package/http.js +4 -2
  3. package/package.json +1 -1
  4. package/sequence.js +1 -0
package/app.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as inspector from 'node:inspector'
2
2
  import os from 'node:os'
3
+ import http from 'node:http'
3
4
  import net from 'node:net'
4
5
  import assert from 'node:assert'
5
6
  import stream from 'node:stream'
@@ -806,46 +807,136 @@ export function makeApp(appConfig, onTerminate) {
806
807
  }
807
808
  }
808
809
 
809
- const inspectBC = new BroadcastChannel('nxt:inspect')
810
- const inspectSet = new Set()
810
+ if (appConfig.inspect !== false) {
811
+ // TODO (fix): What about cluster?
811
812
 
812
- if (serviceWorkerId) {
813
- inspectBC.onmessage = ({ data }) => {
814
- const { type, id } = data
813
+ const inspectBC = new BroadcastChannel('nxt:inspect')
814
+ let inspectOpen = false
815
815
 
816
- if (id !== serviceWorkerId) {
817
- return
818
- }
816
+ if (!isMainThread) {
817
+ inspectBC.onmessage = ({ data }) => {
818
+ const { type, id } = data
819
+
820
+ if (id !== threadId) {
821
+ return
822
+ }
819
823
 
820
- if (type === 'inspect:open') {
821
- // TODO (fix): What happens if you call inspect:open multiple times?
822
- inspector.open(data.port, data.hostname)
823
- } else if (type === 'inspect:close') {
824
- inspector.close()
824
+ if (type === 'inspect:open') {
825
+ // TODO (fix): What happens if you call inspect:open multiple times?
826
+ if (!inspectOpen) {
827
+ inspector.open(data.port, data.hostname)
828
+ inspectOpen = true
829
+ }
830
+ } else if (type === 'inspect:close') {
831
+ if (inspectOpen) {
832
+ inspector.close()
833
+ inspectOpen = false
834
+ }
835
+ }
825
836
  }
826
- }
827
837
 
828
- inspectBC.postMessage({ type: 'inspect:register', id: serviceWorkerId })
829
- destroyers.unshift(() => {
830
- inspector.close()
831
- inspectBC.postMessage({ type: 'inspect:unregister', id: serviceWorkerId })
832
- setTimeout(() => {
833
- inspectBC.close()
834
- }, 100)
835
- })
836
- } else {
837
- inspectBC.onmessage = ({ data }) => {
838
- const { type } = data
838
+ inspectBC.postMessage({
839
+ type: 'inspect:register',
840
+ id: threadId,
841
+ worker: {
842
+ id: threadId,
843
+ name: serviceName,
844
+ module: serviceModule,
845
+ version: serviceVersion,
846
+ workerId: serviceWorkerId,
847
+ instanceId: serviceInstanceId,
848
+ threadId,
849
+ processId: process.pid,
850
+ },
851
+ })
852
+ destroyers.unshift(() => {
853
+ if (inspectOpen) {
854
+ inspector.close()
855
+ inspectOpen = false
856
+ }
857
+ inspectBC.postMessage({ type: 'inspect:unregister', id: threadId })
858
+ setTimeout(() => {
859
+ inspectBC.close()
860
+ }, 100)
861
+ })
862
+ } else {
863
+ const inspectMap = new Set()
864
+
865
+ inspectBC.onmessage = ({ data }) => {
866
+ const { type, worker } = data
839
867
 
840
- if (type === 'inspect:register') {
841
- inspectSet.add(data.id)
842
- } else if (type === 'inspect:unregister') {
843
- inspectSet.delete(data.id)
868
+ if (type === 'inspect:register') {
869
+ inspectMap.add(data.id, worker)
870
+ } else if (type === 'inspect:unregister') {
871
+ inspectMap.delete(data.id)
872
+ }
844
873
  }
874
+ destroyers.unshift(() => inspectBC.close())
875
+
876
+ // TODO (fix): Determinisitc port also in dev mode... hash of something?
877
+ const port =
878
+ appConfig.inspect?.port ?? (isProduction ? 38603 : Math.floor(38000 + Math.random() * 1000))
879
+ const server = http
880
+ .createServer(async (req, res) => {
881
+ try {
882
+ // TOOD (fix); Better matching...
883
+ if (!req.url.startsWith('/inspect')) {
884
+ res.statusCode = 404
885
+ res.end()
886
+ return
887
+ }
888
+
889
+ if (req.method === 'GET') {
890
+ res.end(
891
+ JSON.stringify({
892
+ workers: Array.from(inspectMap.values()),
893
+ }),
894
+ )
895
+ return
896
+ }
897
+
898
+ if (req.method === 'POST') {
899
+ const m = req.url.match(/^\/inspect\/([^/]+)/)
900
+ if (!m) {
901
+ res.statusCode = 404
902
+ res.end()
903
+ return
904
+ } else {
905
+ const { port, hostname } = await json(req)
906
+
907
+ // TODO (fix): What about return value & errors?
908
+ inspectBC.postMessage({
909
+ type: port || hostname ? 'inspect:open' : 'inspect:close',
910
+ id: m[1],
911
+ port,
912
+ hostname,
913
+ })
914
+
915
+ res.end()
916
+ return
917
+ }
918
+ }
919
+
920
+ res.statusCode = 405
921
+ res.end()
922
+ } catch (err) {
923
+ if (res.headersSent) {
924
+ res.destroy(err)
925
+ } else {
926
+ res.statusCode = 500
927
+ res.end()
928
+ }
929
+ }
930
+ })
931
+ .listen(port)
932
+
933
+ logger.debug({ port }, 'inspect listening')
934
+
935
+ destroyers.unshift(() => new Promise((resolve) => server.close(resolve)))
845
936
  }
846
- destroyers.unshift(() => inspectBC.close())
847
937
  }
848
938
 
939
+ // TODO (fix): Deprecate
849
940
  if (appConfig.http) {
850
941
  const httpConfig = { ...appConfig.http, ...config.http }
851
942
 
@@ -868,36 +959,6 @@ export function makeApp(appConfig, onTerminate) {
868
959
  return next()
869
960
  }
870
961
  },
871
- async ({ req, res }, next) => {
872
- if (req.url.startsWith('/inspect')) {
873
- if (req.method === 'GET') {
874
- res.end(JSON.stringify({ workers: Array.from(inspectSet).map((id) => ({ id })) }))
875
- } else if (req.method === 'POST') {
876
- const m = req.url.match(/^\/inspect\/([^/]+)/)
877
- if (!m) {
878
- res.statusCode = 404
879
- res.end()
880
- } else {
881
- const { port, hostname } = await json(req)
882
-
883
- // TODO (fix): What about return value & errors?
884
- inspectBC.postMessage({
885
- type: port || hostname ? 'inspect:open' : 'inspect:close',
886
- id: m[1],
887
- port,
888
- hostname,
889
- })
890
-
891
- res.end()
892
- }
893
- } else {
894
- res.statusCode = 405
895
- res.end()
896
- }
897
- } else {
898
- return next()
899
- }
900
- },
901
962
  appConfig.http.request
902
963
  ? appConfig.http.request
903
964
  : typeof appConfig.http === 'function'
package/http.js CHANGED
@@ -53,6 +53,8 @@ export class Context {
53
53
  this.#req = req
54
54
  this.#res = res
55
55
  this.#logger = logger.child({ reqId: this.#id, url: req.url, userAgent: this.#userAgent })
56
+
57
+ res.setHeader('request-id', this.id)
56
58
  }
57
59
 
58
60
  get id() {
@@ -140,8 +142,8 @@ export async function request2(ctx, next) {
140
142
  // Do nothing...
141
143
  } else if (!res.writableEnded) {
142
144
  logger.debug({ res, elapsedTime }, 'request aborted')
143
- } else if (res.statusCode >= 500) {
144
- logger.error({ res, elapsedTime }, 'request error')
145
+ } else if (res.statusCode >= 500 || res.errored) {
146
+ logger.error({ err: res.errored, res, elapsedTime }, 'request error')
145
147
  } else if (res.statusCode >= 400) {
146
148
  logger.warn({ res, elapsedTime }, 'request failed')
147
149
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/lib",
3
- "version": "21.5.2",
3
+ "version": "21.5.4",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "type": "module",
package/sequence.js CHANGED
@@ -92,6 +92,7 @@ export class Sequence {
92
92
  assert(false, part)
93
93
  }
94
94
  }
95
+ assert(this.#identity === 0 || this.#parts.length > 0)
95
96
  } else if (typeof value === 'string') {
96
97
  const [countStr, token] = value.split('-')
97
98
  const count = parseInt(countStr)