request-drain 1.0.0 → 1.1.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.
package/README.md CHANGED
@@ -28,6 +28,7 @@ When deploying a new version of a service, existing HTTP requests should be allo
28
28
  * ✅ No runtime dependencies
29
29
  * ✅ Multiple middleware layers can track the same request safely
30
30
  * ✅ Predictable shutdown behavior with optional timeout
31
+ * ✅ Track arbitrary async tasks alongside HTTP requests
31
32
 
32
33
  ---
33
34
 
@@ -93,6 +94,32 @@ In this example the middleware:
93
94
 
94
95
  ---
95
96
 
97
+ ## Tracking Async Tasks
98
+
99
+ In addition to HTTP requests, `startTask()` lets you track arbitrary async work — such as background jobs, queue processing, or cleanup routines — within the same shutdown coordination.
100
+
101
+ ```ts
102
+ const handle = registry.register()
103
+
104
+ handle.onAbort(async () => {
105
+ await handle.waitUntilIdle(5_000)
106
+ })
107
+
108
+ // Start a task before doing async work
109
+ const task = handle.startTask()
110
+
111
+ doSomethingAsync().finally(() => {
112
+ // Signal that the task is complete
113
+ task.done()
114
+ })
115
+ ```
116
+
117
+ `startTask()` returns a `Task` object with a single `done()` method. Call `done()` when the work is finished so the handle can reach idle state and shutdown can proceed.
118
+
119
+ This is useful when your middleware or service component kicks off work that is not tied to an HTTP request lifecycle.
120
+
121
+ ---
122
+
96
123
  ## Multiple Middlewares
97
124
 
98
125
  Each middleware registers its own handle. The registry ensures that a request passing through multiple middlewares is tracked independently per handle without double-counting within a handle.
@@ -1,4 +1,4 @@
1
- import type { OnAbortFn, RequestConfigs } from "./types.js";
1
+ import type { OnAbortFn, RequestConfigs, Task } from "./types.js";
2
2
  import type { RequestTracker } from "./RequestTracker.js";
3
3
  import type { IncomingMessage } from "node:http";
4
4
  export declare const SHUTDOWN_KEY: unique symbol;
@@ -38,6 +38,7 @@ export declare class ShutdownHandle {
38
38
  * release external resources.
39
39
  */
40
40
  onAbort(fn: OnAbortFn): void;
41
+ startTask(): Task;
41
42
  /**
42
43
  * Registers a request with this handle.
43
44
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ShutdownHandle.d.ts","sourceRoot":"","sources":["../src/ShutdownHandle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,cAAc,EAAC,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,WAAW,CAAC;AAE/C,eAAO,MAAM,YAAY,eAAqB,CAAA;AAE9C;;;;;;;;GAQG;AACH,qBAAa,cAAc;;gBAUvB,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,EACnC,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI;IAQtC;;OAEG;IACH,IAAI,MAAM,YAET;IAED;;;;OAIG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB/C;;;;OAIG;IACH,IAAI,UAAU,YAEb;IAEK,CAAC,YAAY,CAAC;IAOpB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,EAAE,SAAS;IAIrB;;;;OAIG;IACH,OAAO,CAAC,GAAG,EAAE,eAAe;CAY7B"}
1
+ {"version":3,"file":"ShutdownHandle.d.ts","sourceRoot":"","sources":["../src/ShutdownHandle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,cAAc,EAAE,IAAI,EAAC,MAAM,YAAY,CAAC;AAChE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,WAAW,CAAC;AAE/C,eAAO,MAAM,YAAY,eAAqB,CAAA;AAE9C;;;;;;;;GAQG;AACH,qBAAa,cAAc;;gBAUvB,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,EACnC,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI;IAQtC;;OAEG;IACH,IAAI,MAAM,YAET;IAED;;;;OAIG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB/C;;;;OAIG;IACH,IAAI,UAAU,YAEb;IAEK,CAAC,YAAY,CAAC;IAOpB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,EAAE,SAAS;IAIrB,SAAS,IAAI,IAAI;IAWjB;;;;OAIG;IACH,OAAO,CAAC,GAAG,EAAE,eAAe;CAY7B"}
@@ -72,6 +72,16 @@ export class ShutdownHandle {
72
72
  onAbort(fn) {
73
73
  this.#abortFns.push(fn);
74
74
  }
75
+ startTask() {
76
+ const id = Symbol();
77
+ this.#requestTracker.track(id);
78
+ const task = {
79
+ done: () => {
80
+ this.#requestTracker.release(id);
81
+ }
82
+ };
83
+ return task;
84
+ }
75
85
  /**
76
86
  * Registers a request with this handle.
77
87
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ShutdownHandle.js","sourceRoot":"","sources":["../src/ShutdownHandle.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,mBAAmB,EAAC,MAAM,YAAY,CAAC;AAG/C,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;AAE9C;;;;;;;;GAQG;AACH,MAAM,OAAO,cAAc;IAEhB,SAAS,GAAgB,EAAE,CAAA;IAC3B,eAAe,CAAgB;IAC/B,eAAe,CAAsB;IACrC,cAAc,CAAsB;IACpC,eAAe,CAAgB;IACxC,SAAS,GAAY,KAAK,CAAA;IAE1B,YACE,cAA8B,EAC9B,cAA8B,EAC9B,aAAmC,EACnC,cAAoC;QAEpC,IAAI,CAAC,eAAe,GAAG,cAAc,CAAA;QACrC,IAAI,CAAC,eAAe,GAAG,cAAc,CAAA;QACrC,IAAI,CAAC,eAAe,GAAG,cAAc,CAAA;QACrC,IAAI,CAAC,cAAc,GAAG,aAAa,CAAA;IACrC,CAAC;IAED;;OAEG;IACH,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAA;IACrC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,aAAa,CAAC,GAAW;QAC7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,OAAO,OAAO,EAAE,CAAA;YAClB,CAAC;YAED,MAAM,MAAM,GAAG,GAAG,EAAE;gBAClB,YAAY,CAAC,OAAO,CAAC,CAAA;gBACrB,OAAO,EAAE,CAAA;YACX,CAAC,CAAA;YAED,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC9B,OAAO,EAAE,CAAA;gBACT,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;YACtC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,CAAA;YAEf,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACrC,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;;OAIG;IACH,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAED,KAAK,CAAC,CAAC,YAAY,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QACrB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,MAAM,EAAE,EAAE,CAAA;QACZ,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,EAAa;QACnB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACzB,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,GAAoB;QAC1B,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,mBAAmB,EAAE,CAAA;QAC5E,MAAM,EAAE,GAAG,aAAa,CAAC,EAAE,CAAA;QAC3B,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC9B,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;QAEvB,IAAI,aAAa,CAAC,KAAK,EAAE,CAAC;YACxB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;YAC5C,aAAa,CAAC,KAAK,GAAG,KAAK,CAAA;YAC3B,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAA;QACjD,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"ShutdownHandle.js","sourceRoot":"","sources":["../src/ShutdownHandle.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { OnAbortFn } from "./types.js";
1
+ export type { OnAbortFn, Task } from "./types.js";
2
2
  export { ShutdownRegistry } from "./ShutdownRegistry.js";
3
3
  export type { ShutdownHandle } from "./ShutdownHandle.js";
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAC,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAC,SAAS,EAAE,IAAI,EAAC,MAAM,YAAY,CAAC;AAChD,OAAO,EAAC,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -9,4 +9,7 @@ export type RequestConfig = {
9
9
  * May perform asynchronous cleanup.
10
10
  */
11
11
  export type OnAbortFn = () => void | Promise<void>;
12
+ export interface Task {
13
+ done(): void;
14
+ }
12
15
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,WAAW,CAAC;AAE/C,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;AAEpE,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,OAAO,CAAA;IACd,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,WAAW,CAAC;AAE/C,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;AAEpE,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,OAAO,CAAA;IACd,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAElD,MAAM,WAAW,IAAI;IACnB,IAAI,IAAI,IAAI,CAAA;CACb"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "request-drain",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Gracefully drain HTTP requests before shutting down a Node.js service.",
5
5
  "license": "MIT",
6
6
  "author": "Pascal Pfeifer <pascal@pfeifer.zone>",