@rotorsoft/act-http 1.10.13 → 1.10.14
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/.tsbuildinfo +1 -1
- package/dist/@types/api/in-flight.d.ts +41 -0
- package/dist/@types/api/in-flight.d.ts.map +1 -0
- package/dist/@types/hono/index.d.ts +9 -5
- package/dist/@types/hono/index.d.ts.map +1 -1
- package/dist/@types/openapi/index.d.ts.map +1 -1
- package/dist/@types/receiver/start.d.ts.map +1 -1
- package/dist/@types/trpc/index.d.ts +8 -4
- package/dist/@types/trpc/index.d.ts.map +1 -1
- package/dist/chunk-FXVWAQ2D.js +55 -0
- package/dist/chunk-FXVWAQ2D.js.map +1 -0
- package/dist/hono/index.cjs +62 -1
- package/dist/hono/index.cjs.map +1 -1
- package/dist/hono/index.js +14 -1
- package/dist/hono/index.js.map +1 -1
- package/dist/openapi/index.cjs +3 -2
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.js +3 -2
- package/dist/openapi/index.js.map +1 -1
- package/dist/receiver/index.cjs +54 -29
- package/dist/receiver/index.cjs.map +1 -1
- package/dist/receiver/index.js +6 -29
- package/dist/receiver/index.js.map +1 -1
- package/dist/trpc/index.cjs +59 -1
- package/dist/trpc/index.cjs.map +1 -1
- package/dist/trpc/index.js +11 -1
- package/dist/trpc/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module act-http/api/in-flight
|
|
3
|
+
*
|
|
4
|
+
* Tells a duplicate of a delivery that is still running apart from a
|
|
5
|
+
* duplicate of one that already succeeded. An {@link IdempotencyStore}
|
|
6
|
+
* can't: its `claim` returns `false` in both cases. Answering the first
|
|
7
|
+
* "accepted, stop retrying" loses the delivery if the original then fails
|
|
8
|
+
* and releases the key, so the receiver and the generated API both ask
|
|
9
|
+
* the sender to retry while the original is in flight.
|
|
10
|
+
*
|
|
11
|
+
* Internal — not re-exported from the package. Process-local, which
|
|
12
|
+
* matches `InMemoryIdempotencyStore`'s single-process scope.
|
|
13
|
+
*/
|
|
14
|
+
import type { IdempotencyStore } from "@rotorsoft/act-ops/idempotency";
|
|
15
|
+
/** A wrapped store plus the in-flight check it maintains. @internal */
|
|
16
|
+
export type InFlightTracker = {
|
|
17
|
+
/** Pass this to the code that claims, commits, and releases. */
|
|
18
|
+
readonly store: IdempotencyStore;
|
|
19
|
+
/**
|
|
20
|
+
* True while a claim on `key` is pending, or was won and is not yet
|
|
21
|
+
* committed or released. Read it after your own claim lost.
|
|
22
|
+
*/
|
|
23
|
+
in_flight(key: string): boolean;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Wraps `store` so claims are counted per key. A key is counted **before**
|
|
27
|
+
* the claim is awaited, not when its reply arrives: with an async store
|
|
28
|
+
* the loser's `false` can arrive before the winner's `true`, and marking
|
|
29
|
+
* only on the winner's reply would leave the loser a window to see the key
|
|
30
|
+
* unmarked and be answered as a settled duplicate. A claim that loses (or
|
|
31
|
+
* throws) uncounts itself at once; a claim that wins stays counted until
|
|
32
|
+
* its commit or release lands.
|
|
33
|
+
*
|
|
34
|
+
* A concurrent duplicate of an already-committed key can therefore read
|
|
35
|
+
* as in flight while another duplicate's claim is pending. That costs one
|
|
36
|
+
* extra retry, never a lost delivery.
|
|
37
|
+
*
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
export declare function track_in_flight(store: IdempotencyStore): InFlightTracker;
|
|
41
|
+
//# sourceMappingURL=in-flight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-flight.d.ts","sourceRoot":"","sources":["../../../src/api/in-flight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAEvE,uEAAuE;AACvE,MAAM,MAAM,eAAe,GAAG;IAC5B,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC;;;OAGG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,eAAe,CAkDxE"}
|
|
@@ -31,10 +31,13 @@ export type ActMiddlewareVariables = {
|
|
|
31
31
|
* - `idempotency` (optional) — when set, the route honors
|
|
32
32
|
* `Idempotency-Key` via {@link withIdempotency}. The host
|
|
33
33
|
* supplies the `IdempotencyStore`; `keyFrom` defaults to reading
|
|
34
|
-
* the `Idempotency-Key` header.
|
|
35
|
-
*
|
|
36
|
-
* cache the original handler's result
|
|
37
|
-
*
|
|
34
|
+
* the `Idempotency-Key` header. A duplicate of a key that already
|
|
35
|
+
* succeeded gets `409 Conflict` — the contract intentionally doesn't
|
|
36
|
+
* cache the original handler's result. A duplicate that arrives
|
|
37
|
+
* while the original is still running gets a retryable
|
|
38
|
+
* `503` + `Retry-After` instead, because the original may yet fail
|
|
39
|
+
* and release the key, and a client told "already used" would never
|
|
40
|
+
* retry.
|
|
38
41
|
* - `basePath` (optional, default `"/api"`) — Hono basePath the
|
|
39
42
|
* routes mount under.
|
|
40
43
|
*/
|
|
@@ -106,7 +109,8 @@ export declare function authenticated(extractor: ActorExtractor): MiddlewareHand
|
|
|
106
109
|
* 4. (Optionally) resolves `expectedVersion` for optimistic
|
|
107
110
|
* concurrency.
|
|
108
111
|
* 5. (Optionally) claims the `Idempotency-Key` via
|
|
109
|
-
* {@link withIdempotency} — responds `409` on duplicate
|
|
112
|
+
* {@link withIdempotency} — responds `409` on a duplicate of a
|
|
113
|
+
* committed key, `503` on a duplicate of one still in flight.
|
|
110
114
|
* 6. Calls
|
|
111
115
|
* `app.do(name, { stream, actor, expectedVersion? }, input)`.
|
|
112
116
|
* 7. Maps any thrown framework error onto the shared
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hono/index.ts"],"names":[],"mappings":"AAgDA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hono/index.ts"],"names":[],"mappings":"AAgDA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EACL,KAAK,cAAc,EAMnB,KAAK,UAAU,EAGhB,MAAM,iBAAiB,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,CACf,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,CAAC,EAAE,OAAO,KACP,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,CAAC,EAAE,OAAO,KACP,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;QACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;KACvD,CAAC;IACF;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,cAAc,GACxB,iBAAiB,CAAC;IAAE,SAAS,EAAE,sBAAsB,CAAA;CAAE,CAAC,CAe1D;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH;;;;;;;;GAQG;AACH,KAAK,UAAU,GAAG;IAChB,QAAQ,CAAC,QAAQ,EAAE;QACjB,OAAO,EAAE,MAAM,CACb,MAAM,EACN;YACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SAC3C,CACF,CAAC;KACH,CAAC;IACF,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACxE,CAAC;AAEF,wBAAgB,IAAI,CAAC,IAAI,SAAS,UAAU,GAAG,UAAU,EACvD,GAAG,EAAE,IAAI,EACT,OAAO,EAAE,WAAW,GACnB,IAAI,CAAC;IAAE,SAAS,EAAE,sBAAsB,CAAA;CAAE,CAAC,CA8K7C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/openapi/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/openapi/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/receiver/start.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/receiver/start.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EAEf,eAAe,EAEhB,MAAM,6BAA6B,CAAC;AAKrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,eAAe,CAwHlE"}
|
|
@@ -77,11 +77,14 @@ import { type ActorExtractor, type SseOptions } from "../api/index.js";
|
|
|
77
77
|
* `Idempotency-Key` via the shared
|
|
78
78
|
* {@link withIdempotency} helper. The host supplies the
|
|
79
79
|
* `IdempotencyStore` and a `keyFrom` extractor that reads the key
|
|
80
|
-
* out of the tRPC context (typically a header).
|
|
81
|
-
*
|
|
80
|
+
* out of the tRPC context (typically a header). A duplicate of a key
|
|
81
|
+
* that already succeeded throws a `CONFLICT` `TRPCError` — the
|
|
82
82
|
* receiver-side convention of "ack the duplicate" doesn't carry
|
|
83
83
|
* over because the contract intentionally does not cache the
|
|
84
|
-
* original handler's result.
|
|
84
|
+
* original handler's result. A duplicate that arrives while the
|
|
85
|
+
* original is still running throws a retryable
|
|
86
|
+
* `SERVICE_UNAVAILABLE` (503) instead: the original may yet fail and
|
|
87
|
+
* release the key, and a client told "already used" would never retry.
|
|
85
88
|
*
|
|
86
89
|
* @template Ctx The host's tRPC context shape. Flows end-to-end —
|
|
87
90
|
* procedures see this exact context type (plus `actor`) at
|
|
@@ -158,7 +161,8 @@ export declare function authenticated(extractor: ActorExtractor): AnyTRPCMiddlew
|
|
|
158
161
|
* `ctx.actor`.
|
|
159
162
|
* 2. Resolves the target stream via `options.stream(name, input, ctx)`.
|
|
160
163
|
* 3. (Optionally) claims the `Idempotency-Key` via
|
|
161
|
-
* {@link withIdempotency} — throws `CONFLICT` on duplicate
|
|
164
|
+
* {@link withIdempotency} — throws `CONFLICT` on a duplicate of a
|
|
165
|
+
* committed key, `SERVICE_UNAVAILABLE` on one still in flight.
|
|
162
166
|
* 4. Calls `app.do(name, { stream, actor: ctx.actor }, input)`.
|
|
163
167
|
* 5. Maps any thrown framework error onto a `TRPCError` via
|
|
164
168
|
* {@link toApiError}.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/trpc/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,OAAO,EAAc,KAAK,MAAM,EAAY,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EAErB,KAAK,eAAe,EAErB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/trpc/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,OAAO,EAAc,KAAK,MAAM,EAAY,MAAM,gBAAgB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EAErB,KAAK,eAAe,EAErB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,KAAK,cAAc,EAInB,KAAK,UAAU,EAGhB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,MAAM,WAAW,CAAC,GAAG,IAAI;IAC7B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,CACf,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,GAAG,KACL,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,GAAG,KACL,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;QACjC,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAC;KACpD,CAAC;IACF;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC;CAC3B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,cAAc,GACxB,yBAAyB,CAmB3B;AAsDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH;;;;;;;;;;GAUG;AACH,KAAK,UAAU,GAAG;IAChB,QAAQ,CAAC,QAAQ,EAAE;QACjB,OAAO,EAAE,MAAM,CACb,MAAM,EACN;YACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SAC3C,CACF,CAAC;KACH,CAAC;IACF,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACxE,CAAC;AAEF;;;;;;;;;;GAUG;AACH,KAAK,eAAe,CAAC,IAAI,IAAI,eAAe,CAC1C,gBAAgB,EAChB,IAAI,SAAS;IAAE,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;KAAE,CAAA;CAAE,GAClD;KAAG,CAAC,IAAI,MAAM,QAAQ,GAAG,wBAAwB;CAAE,GACnD,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAC7C,CAAC;AAEF,wBAAgB,IAAI,CAClB,GAAG,SAAS,MAAM,GAAG,MAAM,EAC3B,IAAI,SAAS,UAAU,GAAG,UAAU,EACpC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAsK7D"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// src/api/in-flight.ts
|
|
2
|
+
function track_in_flight(store) {
|
|
3
|
+
const pending = /* @__PURE__ */ new Map();
|
|
4
|
+
const up = (key) => pending.set(key, (pending.get(key) ?? 0) + 1);
|
|
5
|
+
const down = (key) => {
|
|
6
|
+
const left = (pending.get(key) ?? 0) - 1;
|
|
7
|
+
if (left > 0) pending.set(key, left);
|
|
8
|
+
else pending.delete(key);
|
|
9
|
+
};
|
|
10
|
+
const settle = (key, won) => {
|
|
11
|
+
if (!won) down(key);
|
|
12
|
+
return won;
|
|
13
|
+
};
|
|
14
|
+
return {
|
|
15
|
+
in_flight: (key) => pending.has(key),
|
|
16
|
+
store: {
|
|
17
|
+
claim(key, now) {
|
|
18
|
+
up(key);
|
|
19
|
+
let won;
|
|
20
|
+
try {
|
|
21
|
+
won = store.claim(key, now);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
down(key);
|
|
24
|
+
throw err;
|
|
25
|
+
}
|
|
26
|
+
return typeof won === "boolean" ? settle(key, won) : won.then(
|
|
27
|
+
(w) => settle(key, w),
|
|
28
|
+
(err) => {
|
|
29
|
+
down(key);
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
},
|
|
34
|
+
async commit(key, now) {
|
|
35
|
+
try {
|
|
36
|
+
await store.commit(key, now);
|
|
37
|
+
} finally {
|
|
38
|
+
down(key);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
async release(key) {
|
|
42
|
+
try {
|
|
43
|
+
await store.release(key);
|
|
44
|
+
} finally {
|
|
45
|
+
down(key);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
track_in_flight
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=chunk-FXVWAQ2D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/in-flight.ts"],"sourcesContent":["/**\n * @module act-http/api/in-flight\n *\n * Tells a duplicate of a delivery that is still running apart from a\n * duplicate of one that already succeeded. An {@link IdempotencyStore}\n * can't: its `claim` returns `false` in both cases. Answering the first\n * \"accepted, stop retrying\" loses the delivery if the original then fails\n * and releases the key, so the receiver and the generated API both ask\n * the sender to retry while the original is in flight.\n *\n * Internal — not re-exported from the package. Process-local, which\n * matches `InMemoryIdempotencyStore`'s single-process scope.\n */\nimport type { IdempotencyStore } from \"@rotorsoft/act-ops/idempotency\";\n\n/** A wrapped store plus the in-flight check it maintains. @internal */\nexport type InFlightTracker = {\n /** Pass this to the code that claims, commits, and releases. */\n readonly store: IdempotencyStore;\n /**\n * True while a claim on `key` is pending, or was won and is not yet\n * committed or released. Read it after your own claim lost.\n */\n in_flight(key: string): boolean;\n};\n\n/**\n * Wraps `store` so claims are counted per key. A key is counted **before**\n * the claim is awaited, not when its reply arrives: with an async store\n * the loser's `false` can arrive before the winner's `true`, and marking\n * only on the winner's reply would leave the loser a window to see the key\n * unmarked and be answered as a settled duplicate. A claim that loses (or\n * throws) uncounts itself at once; a claim that wins stays counted until\n * its commit or release lands.\n *\n * A concurrent duplicate of an already-committed key can therefore read\n * as in flight while another duplicate's claim is pending. That costs one\n * extra retry, never a lost delivery.\n *\n * @internal\n */\nexport function track_in_flight(store: IdempotencyStore): InFlightTracker {\n const pending = new Map<string, number>();\n const up = (key: string) => pending.set(key, (pending.get(key) ?? 0) + 1);\n const down = (key: string) => {\n const left = (pending.get(key) ?? 0) - 1;\n if (left > 0) pending.set(key, left);\n else pending.delete(key);\n };\n const settle = (key: string, won: boolean) => {\n if (!won) down(key);\n return won;\n };\n return {\n in_flight: (key) => pending.has(key),\n store: {\n claim(key, now) {\n up(key);\n let won: boolean | Promise<boolean>;\n try {\n won = store.claim(key, now);\n } catch (err) {\n down(key);\n throw err;\n }\n return typeof won === \"boolean\"\n ? settle(key, won)\n : won.then(\n (w) => settle(key, w),\n (err: unknown) => {\n down(key);\n throw err;\n }\n );\n },\n async commit(key, now) {\n try {\n await store.commit(key, now);\n } finally {\n down(key);\n }\n },\n async release(key) {\n try {\n await store.release(key);\n } finally {\n down(key);\n }\n },\n },\n };\n}\n"],"mappings":";AAyCO,SAAS,gBAAgB,OAA0C;AACxE,QAAM,UAAU,oBAAI,IAAoB;AACxC,QAAM,KAAK,CAAC,QAAgB,QAAQ,IAAI,MAAM,QAAQ,IAAI,GAAG,KAAK,KAAK,CAAC;AACxE,QAAM,OAAO,CAAC,QAAgB;AAC5B,UAAM,QAAQ,QAAQ,IAAI,GAAG,KAAK,KAAK;AACvC,QAAI,OAAO,EAAG,SAAQ,IAAI,KAAK,IAAI;AAAA,QAC9B,SAAQ,OAAO,GAAG;AAAA,EACzB;AACA,QAAM,SAAS,CAAC,KAAa,QAAiB;AAC5C,QAAI,CAAC,IAAK,MAAK,GAAG;AAClB,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,WAAW,CAAC,QAAQ,QAAQ,IAAI,GAAG;AAAA,IACnC,OAAO;AAAA,MACL,MAAM,KAAK,KAAK;AACd,WAAG,GAAG;AACN,YAAI;AACJ,YAAI;AACF,gBAAM,MAAM,MAAM,KAAK,GAAG;AAAA,QAC5B,SAAS,KAAK;AACZ,eAAK,GAAG;AACR,gBAAM;AAAA,QACR;AACA,eAAO,OAAO,QAAQ,YAClB,OAAO,KAAK,GAAG,IACf,IAAI;AAAA,UACF,CAAC,MAAM,OAAO,KAAK,CAAC;AAAA,UACpB,CAAC,QAAiB;AAChB,iBAAK,GAAG;AACR,kBAAM;AAAA,UACR;AAAA,QACF;AAAA,MACN;AAAA,MACA,MAAM,OAAO,KAAK,KAAK;AACrB,YAAI;AACF,gBAAM,MAAM,OAAO,KAAK,GAAG;AAAA,QAC7B,UAAE;AACA,eAAK,GAAG;AAAA,QACV;AAAA,MACF;AAAA,MACA,MAAM,QAAQ,KAAK;AACjB,YAAI;AACF,gBAAM,MAAM,QAAQ,GAAG;AAAA,QACzB,UAAE;AACA,eAAK,GAAG;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
package/dist/hono/index.cjs
CHANGED
|
@@ -54,6 +54,57 @@ var zValidator = zValidatorFunction;
|
|
|
54
54
|
var import_hono = require("hono");
|
|
55
55
|
var import_streaming = require("hono/streaming");
|
|
56
56
|
|
|
57
|
+
// src/api/in-flight.ts
|
|
58
|
+
function track_in_flight(store) {
|
|
59
|
+
const pending = /* @__PURE__ */ new Map();
|
|
60
|
+
const up = (key) => pending.set(key, (pending.get(key) ?? 0) + 1);
|
|
61
|
+
const down = (key) => {
|
|
62
|
+
const left = (pending.get(key) ?? 0) - 1;
|
|
63
|
+
if (left > 0) pending.set(key, left);
|
|
64
|
+
else pending.delete(key);
|
|
65
|
+
};
|
|
66
|
+
const settle2 = (key, won) => {
|
|
67
|
+
if (!won) down(key);
|
|
68
|
+
return won;
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
in_flight: (key) => pending.has(key),
|
|
72
|
+
store: {
|
|
73
|
+
claim(key, now) {
|
|
74
|
+
up(key);
|
|
75
|
+
let won;
|
|
76
|
+
try {
|
|
77
|
+
won = store.claim(key, now);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
down(key);
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
return typeof won === "boolean" ? settle2(key, won) : won.then(
|
|
83
|
+
(w) => settle2(key, w),
|
|
84
|
+
(err) => {
|
|
85
|
+
down(key);
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
},
|
|
90
|
+
async commit(key, now) {
|
|
91
|
+
try {
|
|
92
|
+
await store.commit(key, now);
|
|
93
|
+
} finally {
|
|
94
|
+
down(key);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
async release(key) {
|
|
98
|
+
try {
|
|
99
|
+
await store.release(key);
|
|
100
|
+
} finally {
|
|
101
|
+
down(key);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
57
108
|
// src/api/errors.ts
|
|
58
109
|
var import_act = require("@rotorsoft/act");
|
|
59
110
|
var ERROR_MAP = {
|
|
@@ -19919,6 +19970,7 @@ function hono(app, options) {
|
|
|
19919
19970
|
);
|
|
19920
19971
|
api.use("*", authenticated(options.actor));
|
|
19921
19972
|
const key_from = options.idempotency?.keyFrom ?? default_key_from;
|
|
19973
|
+
const tracker = options.idempotency ? track_in_flight(options.idempotency.store) : void 0;
|
|
19922
19974
|
if (options.sse) {
|
|
19923
19975
|
const sse_config = resolveSseConfig(options.sse);
|
|
19924
19976
|
const sse_counter = new SseConnectionCounter(sse_config.maxConnections);
|
|
@@ -20015,10 +20067,19 @@ function hono(app, options) {
|
|
|
20015
20067
|
return c.json(body, 400);
|
|
20016
20068
|
}
|
|
20017
20069
|
const outcome = await withIdempotency(
|
|
20018
|
-
|
|
20070
|
+
tracker.store,
|
|
20019
20071
|
key,
|
|
20020
20072
|
() => app.do(action_name, target, raw)
|
|
20021
20073
|
);
|
|
20074
|
+
if (outcome.deduped && tracker.in_flight(key)) {
|
|
20075
|
+
const body = {
|
|
20076
|
+
error: "ServiceUnavailable",
|
|
20077
|
+
detail: "Idempotency-Key in flight; the original request has not finished, retry later",
|
|
20078
|
+
code: "IN_FLIGHT"
|
|
20079
|
+
};
|
|
20080
|
+
c.header("Retry-After", "1");
|
|
20081
|
+
return c.json(body, 503);
|
|
20082
|
+
}
|
|
20022
20083
|
if (outcome.deduped) {
|
|
20023
20084
|
const body = {
|
|
20024
20085
|
error: "Conflict",
|