@crewhaus/idempotency-keys 0.3.2 → 0.4.2
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/dist/index.d.ts +11 -4
- package/dist/index.js +27 -13
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -7,11 +7,18 @@ export interface IdempotencyStore<TValue = unknown> {
|
|
|
7
7
|
size(): number;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* Compose a stable key from a job id
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Compose a stable key from a job id. We hash so the key fits the typical
|
|
11
|
+
* kv-store key-length limits regardless of job-id shape.
|
|
12
|
+
*
|
|
13
|
+
* `discriminator` partitions the key space for callers whose dedupe unit is
|
|
14
|
+
* NARROWER than the job id — a graph node that must re-run once per attempt,
|
|
15
|
+
* say. It defaults to `0`, which is what queue redelivery wants and what the
|
|
16
|
+
* content-derived callers (`target-managed`, `target-browser-driver`) already
|
|
17
|
+
* pass explicitly, so their keys are unchanged. Passing a per-delivery
|
|
18
|
+
* counter here defeats redelivery dedupe: don't, unless re-running is the
|
|
19
|
+
* point.
|
|
13
20
|
*/
|
|
14
|
-
export declare function idempotencyKey(jobId: string,
|
|
21
|
+
export declare function idempotencyKey(jobId: string, discriminator?: number): IdempotencyKey;
|
|
15
22
|
export type InMemoryStoreOptions = {
|
|
16
23
|
readonly now?: () => number;
|
|
17
24
|
};
|
package/dist/index.js
CHANGED
|
@@ -2,15 +2,22 @@
|
|
|
2
2
|
* Catalog R7 `idempotency-keys` — Section 23 BATCH.
|
|
3
3
|
*
|
|
4
4
|
* Per-key cached-result store the BATCH consumer wraps the user's
|
|
5
|
-
* handler with so a job that
|
|
6
|
-
* crash
|
|
7
|
-
*
|
|
5
|
+
* handler with, so a job that ALREADY COMPLETED and comes back anyway
|
|
6
|
+
* (a crash or a lost ack between the handler returning and the queue
|
|
7
|
+
* being told, an expired visibility lease) returns the cached value
|
|
8
|
+
* without re-invoking the model.
|
|
8
9
|
*
|
|
9
|
-
* Key shape: `idempotencyKey(jobId
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* Key shape: `idempotencyKey(jobId)` — the key is the job's IDENTITY and
|
|
11
|
+
* nothing else. It deliberately does NOT include the attempt counter: a
|
|
12
|
+
* redelivery (crash → retry, a swallowed ack, a visibility lease that
|
|
13
|
+
* collided with another consumer) is precisely the case the cache exists
|
|
14
|
+
* to serve, and every queue adapter that tracks attempts hands the
|
|
15
|
+
* redelivery a *higher* attempt number. Folding the attempt into the key
|
|
16
|
+
* therefore guaranteed a miss on exactly the path that matters and made
|
|
17
|
+
* the configured window unreachable.
|
|
18
|
+
*
|
|
19
|
+
* Only SUCCESSFUL results are cached (see `withIdempotency`), so a
|
|
20
|
+
* failed attempt never suppresses its own retry.
|
|
14
21
|
*
|
|
15
22
|
* The default `createInMemoryIdempotencyStore` is a Map with a per-key
|
|
16
23
|
* TTL. Eviction happens lazily on next get/set; tests can override the
|
|
@@ -18,12 +25,19 @@
|
|
|
18
25
|
*/
|
|
19
26
|
import { createHash } from "node:crypto";
|
|
20
27
|
/**
|
|
21
|
-
* Compose a stable key from a job id
|
|
22
|
-
*
|
|
23
|
-
*
|
|
28
|
+
* Compose a stable key from a job id. We hash so the key fits the typical
|
|
29
|
+
* kv-store key-length limits regardless of job-id shape.
|
|
30
|
+
*
|
|
31
|
+
* `discriminator` partitions the key space for callers whose dedupe unit is
|
|
32
|
+
* NARROWER than the job id — a graph node that must re-run once per attempt,
|
|
33
|
+
* say. It defaults to `0`, which is what queue redelivery wants and what the
|
|
34
|
+
* content-derived callers (`target-managed`, `target-browser-driver`) already
|
|
35
|
+
* pass explicitly, so their keys are unchanged. Passing a per-delivery
|
|
36
|
+
* counter here defeats redelivery dedupe: don't, unless re-running is the
|
|
37
|
+
* point.
|
|
24
38
|
*/
|
|
25
|
-
export function idempotencyKey(jobId,
|
|
26
|
-
return createHash("sha256").update(`${jobId}:${
|
|
39
|
+
export function idempotencyKey(jobId, discriminator = 0) {
|
|
40
|
+
return createHash("sha256").update(`${jobId}:${discriminator}`).digest("hex").slice(0, 24);
|
|
27
41
|
}
|
|
28
42
|
export function createInMemoryIdempotencyStore(opts = {}) {
|
|
29
43
|
const now = opts.now ?? Date.now;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewhaus/idempotency-keys",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Idempotency-key dedup store for the BATCH consumer (Section 23 BATCH)",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"test": "bun test src"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@crewhaus/errors": "0.
|
|
18
|
+
"@crewhaus/errors": "0.4.2"
|
|
19
19
|
},
|
|
20
20
|
"license": "Apache-2.0",
|
|
21
21
|
"author": {
|