@ultimat3/action 16.0.0 → 18.0.0
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/action",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "18.0.0",
|
|
4
4
|
"description": "The action primitive: one declaration projected to route, OpenAPI, client, MCP tool, job handle, tests",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -27,17 +27,17 @@
|
|
|
27
27
|
"LICENSE"
|
|
28
28
|
],
|
|
29
29
|
"engines": {
|
|
30
|
-
"bun": ">=1.
|
|
30
|
+
"bun": ">=1.4.0"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
34
34
|
"test": "bun test"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@ultimat3/cache": "
|
|
38
|
-
"@ultimat3/core": "
|
|
39
|
-
"@ultimat3/http": "
|
|
40
|
-
"@ultimat3/policy": "
|
|
41
|
-
"@ultimat3/schema": "
|
|
37
|
+
"@ultimat3/cache": "18.0.0",
|
|
38
|
+
"@ultimat3/core": "18.0.0",
|
|
39
|
+
"@ultimat3/http": "18.0.0",
|
|
40
|
+
"@ultimat3/policy": "18.0.0",
|
|
41
|
+
"@ultimat3/schema": "18.0.0"
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* and for tests, and refused at registration under a `shared` declaration — its `scope` says so.
|
|
4
4
|
* Shaped after `@ultimat3/http`'s `memoryRateLimitStore`, including the deliberate eviction order.
|
|
5
5
|
*/
|
|
6
|
-
import { uuid } from '@ultimat3/core';
|
|
6
|
+
import { finiteCount, uuid } from '@ultimat3/core';
|
|
7
7
|
import type {
|
|
8
8
|
IdempotencyFailure,
|
|
9
9
|
IdempotencyRecord,
|
|
@@ -47,8 +47,21 @@ export class MemoryIdempotencyStore implements IdempotencyStore {
|
|
|
47
47
|
#lastSweepMs = Number.NEGATIVE_INFINITY;
|
|
48
48
|
|
|
49
49
|
constructor(options: MemoryIdempotencyStoreOptions = {}) {
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
// Screened, not clamped: `Math.floor(NaN)` is `NaN`, so `size > maxKeys` is false for every
|
|
51
|
+
// size and `now - at > windowMs` is false for every record — a table with no cap, holding keys
|
|
52
|
+
// that never expire, out of a `Math.max` that reads like a guard.
|
|
53
|
+
this.windowMs = finiteCount(
|
|
54
|
+
'MemoryIdempotencyStore',
|
|
55
|
+
'windowMs',
|
|
56
|
+
options.windowMs ?? DEFAULT_IDEMPOTENCY_WINDOW_MS,
|
|
57
|
+
1,
|
|
58
|
+
);
|
|
59
|
+
this.#maxKeys = finiteCount(
|
|
60
|
+
'MemoryIdempotencyStore',
|
|
61
|
+
'maxKeys',
|
|
62
|
+
options.maxKeys ?? DEFAULT_MAX_IDEMPOTENCY_KEYS,
|
|
63
|
+
1,
|
|
64
|
+
);
|
|
52
65
|
// Batched down to 90% so the eviction sort is paid once per 10% of the cap, not per write.
|
|
53
66
|
this.#evictTo = Math.max(1, Math.floor(this.#maxKeys * 0.9));
|
|
54
67
|
this.#now = options.now ?? ((): number => Date.now());
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* without it, `replicas: 3` means a retry that lands elsewhere re-runs a committed handler.
|
|
5
5
|
* Statements are spelled out so an agent can run the exact one it saw in a log.
|
|
6
6
|
*/
|
|
7
|
-
import { logger, uuid } from '@ultimat3/core';
|
|
7
|
+
import { finiteCount, logger, uuid } from '@ultimat3/core';
|
|
8
8
|
import { IdempotencyStatusUnknownError } from './errors';
|
|
9
9
|
import type {
|
|
10
10
|
IdempotencyFailure,
|
|
@@ -172,7 +172,14 @@ export interface PostgresIdempotencyStore extends IdempotencyStore {
|
|
|
172
172
|
export function postgresIdempotencyStore(
|
|
173
173
|
options: PostgresIdempotencyStoreOptions,
|
|
174
174
|
): PostgresIdempotencyStore {
|
|
175
|
-
|
|
175
|
+
// The same screen as the memory store's, on the number that becomes `windowSecs` and is bound
|
|
176
|
+
// into every statement below: `Math.floor(NaN)` is `NaN`, and NaN/1000 is what reaches Postgres.
|
|
177
|
+
const windowMs = finiteCount(
|
|
178
|
+
'postgresIdempotencyStore',
|
|
179
|
+
'windowMs',
|
|
180
|
+
options.windowMs ?? DEFAULT_IDEMPOTENCY_WINDOW_MS,
|
|
181
|
+
1,
|
|
182
|
+
);
|
|
176
183
|
const windowSecs = windowMs / 1000;
|
|
177
184
|
const exec = options.executor;
|
|
178
185
|
const now = options.now ?? ((): number => Date.now());
|