velocious 1.0.683 → 1.0.685

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 (41) hide show
  1. package/README.md +2 -1
  2. package/build/background-jobs/pooled-runner-child.js +29 -1
  3. package/build/background-jobs/types.js +1 -0
  4. package/build/background-jobs/worker.js +8 -2
  5. package/build/configuration-types.js +1 -1
  6. package/build/http-server/client/index.js +15 -0
  7. package/build/http-server/client/request.js +44 -0
  8. package/build/http-server/client/websocket-request.js +45 -0
  9. package/build/http-server/worker-handler/in-process.js +7 -1
  10. package/build/http-server/worker-handler/worker-thread.js +5 -0
  11. package/build/src/background-jobs/pooled-runner-child.js +31 -2
  12. package/build/src/background-jobs/types.d.ts +5 -0
  13. package/build/src/background-jobs/types.d.ts.map +1 -1
  14. package/build/src/background-jobs/types.js +2 -1
  15. package/build/src/background-jobs/worker.d.ts.map +1 -1
  16. package/build/src/background-jobs/worker.js +9 -3
  17. package/build/src/configuration-types.d.ts +2 -2
  18. package/build/src/configuration-types.js +2 -2
  19. package/build/src/http-server/client/index.d.ts +9 -0
  20. package/build/src/http-server/client/index.d.ts.map +1 -1
  21. package/build/src/http-server/client/index.js +16 -1
  22. package/build/src/http-server/client/request.d.ts +27 -0
  23. package/build/src/http-server/client/request.d.ts.map +1 -1
  24. package/build/src/http-server/client/request.js +42 -1
  25. package/build/src/http-server/client/websocket-request.d.ts +28 -0
  26. package/build/src/http-server/client/websocket-request.d.ts.map +1 -1
  27. package/build/src/http-server/client/websocket-request.js +43 -1
  28. package/build/src/http-server/worker-handler/in-process.d.ts.map +1 -1
  29. package/build/src/http-server/worker-handler/in-process.js +8 -2
  30. package/build/src/http-server/worker-handler/worker-thread.d.ts.map +1 -1
  31. package/build/src/http-server/worker-handler/worker-thread.js +6 -1
  32. package/package.json +4 -4
  33. package/src/background-jobs/pooled-runner-child.js +29 -1
  34. package/src/background-jobs/types.js +1 -0
  35. package/src/background-jobs/worker.js +8 -2
  36. package/src/configuration-types.js +1 -1
  37. package/src/http-server/client/index.js +15 -0
  38. package/src/http-server/client/request.js +44 -0
  39. package/src/http-server/client/websocket-request.js +45 -0
  40. package/src/http-server/worker-handler/in-process.js +7 -1
  41. package/src/http-server/worker-handler/worker-thread.js +5 -0
@@ -19,6 +19,17 @@ export default class VelociousHttpServerClientRequest {
19
19
  this.client = client
20
20
  this.configuration = configuration
21
21
  this.requestParser = new RequestParser({configuration})
22
+
23
+ /**
24
+ * Whether the owning client connection was torn down while this request
25
+ * was still running. Set once by the client on socket teardown and read
26
+ * by handlers that need to settle in-flight work (e.g. admission queue
27
+ * positions) without waiting for the response to be sent.
28
+ * @type {boolean} */
29
+ this.clientDisconnected = false
30
+
31
+ /** @type {Set<() => void>} */
32
+ this.clientDisconnectCallbacks = new Set()
22
33
  }
23
34
 
24
35
  baseURL() { return `${this.protocol()}://${this.hostWithPort()}` }
@@ -114,6 +125,39 @@ export default class VelociousHttpServerClientRequest {
114
125
  rawBody() { return this.getRequestBuffer().getRawBody() }
115
126
  socketRemoteAddress() { return this.client?.remoteAddress }
116
127
 
128
+ /**
129
+ * Marks this request as client-disconnected and runs every registered
130
+ * disconnect callback exactly once. The owning client invokes it when the
131
+ * socket tears down; handlers that register afterwards learn of the
132
+ * disconnect through the `clientDisconnected` field instead.
133
+ * @returns {void}
134
+ */
135
+ markClientDisconnected() {
136
+ if (this.clientDisconnected) return
137
+ this.clientDisconnected = true
138
+ for (const callback of this.clientDisconnectCallbacks) {
139
+ callback()
140
+ }
141
+ this.clientDisconnectCallbacks.clear()
142
+ }
143
+
144
+ /**
145
+ * Registers a callback that fires once when the client connection tears
146
+ * down while this request is still running. Buffered requests cannot rely
147
+ * on the streaming response's `onStreamClose` for that: no stream has
148
+ * been opened yet, so a queued request's queue position is otherwise
149
+ * stranded until its admission deadline.
150
+ * @param {() => void} callback - Disconnect callback.
151
+ * @returns {void}
152
+ */
153
+ onClientDisconnect(callback) {
154
+ if (this.clientDisconnected) {
155
+ callback()
156
+ return
157
+ }
158
+ this.clientDisconnectCallbacks.add(callback)
159
+ }
160
+
117
161
  getRequestBuffer() { return this.getRequestParser().getRequestBuffer() }
118
162
  getRequestParser() { return this.requestParser }
119
163
  }
@@ -50,6 +50,51 @@ export default class VelociousHttpServerClientWebsocketRequest {
50
50
  const queryParams = this._parseQueryParams()
51
51
 
52
52
  this.paramsObject = {...queryParams, ...this.paramsObject}
53
+
54
+ /**
55
+ * Whether the owning client connection was torn down while this request
56
+ * was still running. Websocket requests are session-owned and never
57
+ * enter the client's in-flight request list, so this stays false for
58
+ * them; the field exists so the request union shares one surface.
59
+ * @type {boolean} */
60
+ this.clientDisconnected = false
61
+
62
+ /** @type {Set<() => void>} */
63
+ this.clientDisconnectCallbacks = new Set()
64
+ }
65
+
66
+ /**
67
+ * Marks this request as client-disconnected and runs every registered
68
+ * disconnect callback exactly once. The owning client invokes it when the
69
+ * socket tears down; handlers that register afterwards learn of the
70
+ * disconnect through the `clientDisconnected` field instead. Websocket
71
+ * requests are session-owned and never enter the client's in-flight
72
+ * request list, so this is inert for them; the shared surface keeps the
73
+ * request union uniform.
74
+ * @returns {void}
75
+ */
76
+ markClientDisconnected() {
77
+ if (this.clientDisconnected) return
78
+ this.clientDisconnected = true
79
+ for (const callback of this.clientDisconnectCallbacks) {
80
+ callback()
81
+ }
82
+ this.clientDisconnectCallbacks.clear()
83
+ }
84
+
85
+ /**
86
+ * Registers a callback that fires once when the client connection tears
87
+ * down while this request is still running. See the HTTP request's
88
+ * {@linkcode markClientDisconnected} for the shared-surface note.
89
+ * @param {() => void} callback - Disconnect callback.
90
+ * @returns {void}
91
+ */
92
+ onClientDisconnect(callback) {
93
+ if (this.clientDisconnected) {
94
+ callback()
95
+ return
96
+ }
97
+ this.clientDisconnectCallbacks.add(callback)
53
98
  }
54
99
 
55
100
  baseURL() {
@@ -116,7 +116,13 @@ export default class VelociousHttpServerInProcessHandler {
116
116
  httpClient.abortPendingFileResponses(),
117
117
  httpClient.abortStreamResponses()
118
118
  ])
119
- .then(() => {})
119
+ .then(() => {
120
+ // Buffered responses have no stream to abort, so their in-flight
121
+ // handlers never hear about the socket teardown through the
122
+ // streaming path: notify the running requests directly so they can
123
+ // settle resources (e.g. admission queue positions) in-process.
124
+ httpClient.notifyClientDisconnect()
125
+ })
120
126
  .catch((error) => {
121
127
  this.logger.warn("Failed to abort responses after client close", error)
122
128
  })
@@ -220,6 +220,11 @@ export default class VelociousHttpServerWorkerHandlerWorkerThread {
220
220
  if (client) {
221
221
  settlements.push(client.abortPendingFileResponses())
222
222
  settlements.push(client.abortStreamResponses())
223
+ // Buffered responses have no stream to abort, so their in-flight
224
+ // handlers never hear about the socket teardown through the streaming
225
+ // path: notify the running requests directly so they can settle
226
+ // resources (e.g. admission queue positions) in-process.
227
+ client.notifyClientDisconnect()
223
228
  }
224
229
 
225
230
  for (const [transferId, transfer] of this.fileTransfers) {