valkyries 0.5.0 → 0.6.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/README.md +2 -0
- package/dist/cache/deletes.d.mts +1 -0
- package/dist/cache/deletes.d.mts.map +1 -1
- package/dist/cache/deletes.mjs +11 -3
- package/dist/cache/deletes.mjs.map +1 -1
- package/dist/conditional.d.mts +8 -0
- package/dist/conditional.d.mts.map +1 -0
- package/dist/conditional.mjs +19 -0
- package/dist/conditional.mjs.map +1 -0
- package/dist/delete.d.mts +2 -1
- package/dist/delete.d.mts.map +1 -1
- package/dist/delete.mjs +18 -20
- package/dist/delete.mjs.map +1 -1
- package/dist/idempotency-key.d.mts +5 -0
- package/dist/idempotency-key.d.mts.map +1 -1
- package/dist/idempotency-key.mjs +22 -20
- package/dist/idempotency-key.mjs.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/dist/scripts/idempotency-key-release-if-current.lua +2 -1
- package/dist/scripts/idempotency-key-reserve.lua +26 -0
- package/dist/scripts/unlink-if-value-matches.lua +14 -0
- package/dist/valkey-result.d.mts +2 -0
- package/dist/valkey-result.d.mts.map +1 -0
- package/dist/valkey-result.mjs +9 -0
- package/dist/valkey-result.mjs.map +1 -0
- package/docs/api.md +1 -1
- package/docs/cache.md +13 -0
- package/docs/clients.md +0 -8
- package/docs/conditional-operations.md +24 -0
- package/docs/idempotency-key.md +13 -2
- package/docs/lua-scripts.md +5 -1
- package/docs/utilities.md +1 -39
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -122,6 +122,8 @@ Call `closeValkeyClients()` to close package-managed clients.
|
|
|
122
122
|
- [Bloom filters](docs/bloom-filters.md)
|
|
123
123
|
- [Dynamic config](docs/dynamic-config.md)
|
|
124
124
|
- [Rate limiter](docs/rate-limiter.md)
|
|
125
|
+
- [Idempotency keys](docs/idempotency-key.md)
|
|
126
|
+
- [Conditional operations](docs/conditional-operations.md)
|
|
125
127
|
- [Events and metrics](docs/events-and-metrics.md)
|
|
126
128
|
- [Lua scripts](docs/lua-scripts.md)
|
|
127
129
|
- [Utilities](docs/utilities.md)
|
package/dist/cache/deletes.d.mts
CHANGED
|
@@ -12,6 +12,7 @@ export declare class ValkeyCacheDeletes<K = string> extends ValkeyCacheMutations
|
|
|
12
12
|
static deleteFromCaches<K>(entries: readonly ValkeyCacheDeleteFromCachesEntry<K>[]): Promise<number>;
|
|
13
13
|
static deleteFromCaches(entries: readonly ValkeyCacheDeleteFromCachesEntry<any>[]): Promise<number>;
|
|
14
14
|
static invalidate(prefix: string, client?: GlideClient): Promise<void>;
|
|
15
|
+
static invalidateMany(prefixes: readonly string[], client?: GlideClient): Promise<void>;
|
|
15
16
|
private static deleteSerializedEntriesFromClient;
|
|
16
17
|
}
|
|
17
18
|
//# sourceMappingURL=deletes.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deletes.d.mts","sourceRoot":"","sources":["../../cache/deletes.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAUhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,MAAM,gCAAgC,CAAC,CAAC,GAAG,GAAG,IAAI;IACtD,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;CACpB,CAAC;AAYF,qBAAa,kBAAkB,CAAC,CAAC,GAAG,MAAM,CAAE,SAAQ,oBAAoB,CAAC,CAAC,CAAC;IACnE,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;cA+B3B,qBAAqB,CAAC,GAAG,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBnF,UAAU;WAIG,gBAAgB,CAAC,CAAC,EAC7B,OAAO,EAAE,SAAS,gCAAgC,CAAC,CAAC,CAAC,EAAE,GACtD,OAAO,CAAC,MAAM,CAAC;WACL,gBAAgB,CAC3B,OAAO,EAAE,SAAS,gCAAgC,CAAC,GAAG,CAAC,EAAE,GACxD,OAAO,CAAC,MAAM,CAAC;WAqEL,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,cAAoB;
|
|
1
|
+
{"version":3,"file":"deletes.d.mts","sourceRoot":"","sources":["../../cache/deletes.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAUhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,MAAM,gCAAgC,CAAC,CAAC,GAAG,GAAG,IAAI;IACtD,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;CACpB,CAAC;AAYF,qBAAa,kBAAkB,CAAC,CAAC,GAAG,MAAM,CAAE,SAAQ,oBAAoB,CAAC,CAAC,CAAC;IACnE,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;cA+B3B,qBAAqB,CAAC,GAAG,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBnF,UAAU;WAIG,gBAAgB,CAAC,CAAC,EAC7B,OAAO,EAAE,SAAS,gCAAgC,CAAC,CAAC,CAAC,EAAE,GACtD,OAAO,CAAC,MAAM,CAAC;WACL,gBAAgB,CAC3B,OAAO,EAAE,SAAS,gCAAgC,CAAC,GAAG,CAAC,EAAE,GACxD,OAAO,CAAC,MAAM,CAAC;WAqEL,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,cAAoB;WAIrD,cAAc,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,cAAoB;mBAkB9D,iCAAiC;CA0BvD"}
|
package/dist/cache/deletes.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cacheValkeyClient } from "../clients.mjs";
|
|
2
2
|
import { emitValkeyEvent } from "../events.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { deleteKeysWithLiteralPrefixes } from "../delete.mjs";
|
|
4
4
|
import { normalizeCountResult } from "../utils.mjs";
|
|
5
5
|
import { CACHE_NAMESPACE, INVALIDATION_MARKER_TTL_SECONDS, cacheDeleteWithInvalidationScript, } from "./constants.mjs";
|
|
6
6
|
import { ValkeyCacheMutations } from "./mutations.mjs";
|
|
@@ -116,8 +116,16 @@ export class ValkeyCacheDeletes extends ValkeyCacheMutations {
|
|
|
116
116
|
return deleted;
|
|
117
117
|
}
|
|
118
118
|
static async invalidate(prefix, client = cacheValkeyClient) {
|
|
119
|
-
await
|
|
120
|
-
|
|
119
|
+
await ValkeyCacheDeletes.invalidateMany([prefix], client);
|
|
120
|
+
}
|
|
121
|
+
static async invalidateMany(prefixes, client = cacheValkeyClient) {
|
|
122
|
+
const uniquePrefixes = [...new Set(prefixes)].filter((prefix) => typeof prefix === "string");
|
|
123
|
+
if (uniquePrefixes.length === 0)
|
|
124
|
+
return;
|
|
125
|
+
await deleteKeysWithLiteralPrefixes(client, `${CACHE_NAMESPACE}:*`, uniquePrefixes.map((prefix) => prefix ? `${CACHE_NAMESPACE}:${prefix}:` : `${CACHE_NAMESPACE}:`));
|
|
126
|
+
for (const prefix of uniquePrefixes) {
|
|
127
|
+
emitValkeyEvent("cache:invalidate", { cacheName: prefix });
|
|
128
|
+
}
|
|
121
129
|
}
|
|
122
130
|
static async deleteSerializedEntriesFromClient(client, entries) {
|
|
123
131
|
const cacheKeys = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deletes.mjs","sourceRoot":"","sources":["../../cache/deletes.mts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"deletes.mjs","sourceRoot":"","sources":["../../cache/deletes.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GlideClient } from "@valkey/valkey-glide";
|
|
2
|
+
export type UnlinkIfValueMatchesOptions = {
|
|
3
|
+
/** Optional Valkey client. Defaults to the package cache client. */
|
|
4
|
+
client?: GlideClient;
|
|
5
|
+
};
|
|
6
|
+
/** Atomically unlinks a key only when its stored string value matches the expected value. */
|
|
7
|
+
export declare function unlinkIfValueMatches(key: string, expectedValue: string, options?: UnlinkIfValueMatchesOptions): Promise<boolean>;
|
|
8
|
+
//# sourceMappingURL=conditional.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditional.d.mts","sourceRoot":"","sources":["../conditional.mts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMxD,MAAM,MAAM,2BAA2B,GAAG;IACxC,oEAAoE;IACpE,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,6FAA6F;AAC7F,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,OAAO,CAAC,CAclB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { cacheValkeyClient } from "./clients.mjs";
|
|
2
|
+
import { loadScript, registerScript } from "./scripts.mjs";
|
|
3
|
+
import { stringifyValkeyResult } from "./valkey-result.mjs";
|
|
4
|
+
const unlinkIfValueMatchesScript = registerScript(loadScript("unlink-if-value-matches.lua", import.meta.url));
|
|
5
|
+
/** Atomically unlinks a key only when its stored string value matches the expected value. */
|
|
6
|
+
export async function unlinkIfValueMatches(key, expectedValue, options = {}) {
|
|
7
|
+
if (!key)
|
|
8
|
+
throw new Error("key must not be empty");
|
|
9
|
+
const result = await (options.client ?? cacheValkeyClient).invokeScript(unlinkIfValueMatchesScript, {
|
|
10
|
+
keys: [key],
|
|
11
|
+
args: [expectedValue],
|
|
12
|
+
});
|
|
13
|
+
if (result === 1 || result === 1n)
|
|
14
|
+
return true;
|
|
15
|
+
if (result === 0 || result === 0n)
|
|
16
|
+
return false;
|
|
17
|
+
throw new Error(`Unexpected conditional unlink result: ${stringifyValkeyResult(result)}`);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=conditional.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditional.mjs","sourceRoot":"","sources":["../conditional.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,MAAM,0BAA0B,GAAG,cAAc,CAC/C,UAAU,CAAC,6BAA6B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAC3D,CAAC;AAOF,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,GAAW,EACX,aAAqB,EACrB,UAAuC,EAAE;IAEzC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAEnD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,iBAAiB,CAAC,CAAC,YAAY,CACrE,0BAA0B,EAC1B;QACE,IAAI,EAAE,CAAC,GAAG,CAAC;QACX,IAAI,EAAE,CAAC,aAAa,CAAC;KACtB,CACF,CAAC;IAEF,IAAI,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAChD,MAAM,IAAI,KAAK,CAAC,yCAAyC,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC5F,CAAC"}
|
package/dist/delete.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { GlideClient } from "@valkey/valkey-glide";
|
|
2
|
-
export declare
|
|
2
|
+
export declare function deleteKeysWithPrefix(client: GlideClient, pattern: string): Promise<void>;
|
|
3
|
+
export declare function deleteKeysWithLiteralPrefixes(client: GlideClient, pattern: string, prefixes: readonly string[]): Promise<void>;
|
|
3
4
|
//# sourceMappingURL=delete.d.mts.map
|
package/dist/delete.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete.d.mts","sourceRoot":"","sources":["../delete.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"delete.d.mts","sourceRoot":"","sources":["../delete.mts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,sBAAsB,CAAC;AAIrE,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9F;AAED,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CASf"}
|
package/dist/delete.mjs
CHANGED
|
@@ -1,34 +1,32 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
1
2
|
import { handleValkeyError } from "./errors.mjs";
|
|
2
|
-
|
|
3
|
-
|
|
3
|
+
const DEFAULT_SCAN_COUNT = 500;
|
|
4
|
+
export async function deleteKeysWithPrefix(client, pattern) {
|
|
5
|
+
await scanAndUnlink(client, pattern);
|
|
6
|
+
}
|
|
7
|
+
export async function deleteKeysWithLiteralPrefixes(client, pattern, prefixes) {
|
|
8
|
+
const uniquePrefixes = [...new Set(prefixes)].filter((prefix) => typeof prefix === "string");
|
|
9
|
+
if (uniquePrefixes.length === 0)
|
|
10
|
+
return;
|
|
11
|
+
await scanAndUnlink(client, pattern, (key) => uniquePrefixes.some((prefix) => key.startsWith(prefix)));
|
|
12
|
+
}
|
|
13
|
+
async function scanAndUnlink(client, pattern, matches = () => true) {
|
|
4
14
|
try {
|
|
5
15
|
let cursor = "0";
|
|
6
16
|
do {
|
|
7
|
-
|
|
8
|
-
const result = await client.scan(cursor, { match: pattern });
|
|
17
|
+
const result = await client.scan(cursor, { match: pattern, count: DEFAULT_SCAN_COUNT });
|
|
9
18
|
cursor = result[0];
|
|
10
|
-
const keys = result[1]
|
|
19
|
+
const keys = result[1]
|
|
20
|
+
.map((key) => (typeof key === "string" ? key : Buffer.from(key).toString("utf8")))
|
|
21
|
+
.filter(matches);
|
|
11
22
|
if (keys.length > 0) {
|
|
12
|
-
|
|
13
|
-
// before Promise.all is reached. SonarCloud complains about empty callbacks,
|
|
14
|
-
// so we call a dummy function or use a minimal expression.
|
|
15
|
-
const p = client.unlink(keys);
|
|
16
|
-
p.catch(() => undefined);
|
|
17
|
-
unlinkPromises.push(p);
|
|
18
|
-
// Prevent unbounded memory/concurrency by batching promises
|
|
19
|
-
if (unlinkPromises.length >= 100) {
|
|
20
|
-
await Promise.all(unlinkPromises);
|
|
21
|
-
unlinkPromises.length = 0;
|
|
22
|
-
}
|
|
23
|
+
await client.unlink(keys);
|
|
23
24
|
}
|
|
24
25
|
} while (cursor !== "0");
|
|
25
|
-
if (unlinkPromises.length > 0) {
|
|
26
|
-
await Promise.all(unlinkPromises);
|
|
27
|
-
}
|
|
28
26
|
}
|
|
29
27
|
catch (err) {
|
|
30
28
|
handleValkeyError(err);
|
|
31
29
|
throw err;
|
|
32
30
|
}
|
|
33
|
-
}
|
|
31
|
+
}
|
|
34
32
|
//# sourceMappingURL=delete.mjs.map
|
package/dist/delete.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete.mjs","sourceRoot":"","sources":["../delete.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"delete.mjs","sourceRoot":"","sources":["../delete.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,MAAmB,EAAE,OAAe;IAC7E,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,MAAmB,EACnB,OAAe,EACf,QAA2B;IAE3B,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,GAAG,CAAU,QAAQ,CAAC,CAAC,CAAC,MAAM,CAC3D,CAAC,MAAM,EAAoB,EAAE,CAAC,OAAO,MAAM,KAAK,QAAQ,CACzD,CAAC;IACF,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAExC,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAC3C,cAAc,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CACxD,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,MAAmB,EACnB,OAAe,EACf,UAAoC,GAAG,EAAE,CAAC,IAAI;IAE9C,IAAI,CAAC;QACH,IAAI,MAAM,GAAG,GAAG,CAAC;QAEjB,GAAG,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;YACxF,MAAM,GAAG,MAAM,CAAC,CAAC,CAAW,CAAC;YAC7B,MAAM,IAAI,GAAI,MAAM,CAAC,CAAC,CAAmB;iBACtC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;iBACjF,MAAM,CAAC,OAAO,CAAC,CAAC;YAEnB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC,QAAQ,MAAM,KAAK,GAAG,EAAE;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACvB,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -14,6 +14,11 @@ export type IdempotencyKeyOptions = {
|
|
|
14
14
|
export type ReserveIdempotencyKeyOptions = IdempotencyKeyOptions & {
|
|
15
15
|
/** Optional reservation token. Defaults to crypto.randomUUID(). */
|
|
16
16
|
token?: string;
|
|
17
|
+
/** Opt in to atomically repair persistent existing reservations. */
|
|
18
|
+
repairMissingExpiry?: {
|
|
19
|
+
/** TTL for persistent completed values. Defaults to ttlSeconds. */
|
|
20
|
+
completedTtlSeconds?: number;
|
|
21
|
+
};
|
|
17
22
|
};
|
|
18
23
|
export type IdempotencyReservation = {
|
|
19
24
|
state: "reserved";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idempotency-key.d.mts","sourceRoot":"","sources":["../idempotency-key.mts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"idempotency-key.d.mts","sourceRoot":"","sources":["../idempotency-key.mts"],"names":[],"mappings":"AAKA,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAejE,MAAM,MAAM,mBAAmB,GAAG;IAChC,oEAAoE;IACpE,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,oEAAoE;IACpE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,qBAAqB,GAAG;IACjE,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,mBAAmB,CAAC,EAAE;QACpB,mEAAmE;QACnE,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAC9B;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,KAAK,EAAE,YAAY,GAAG,WAAW,CAAA;CAAE,CAAC;AAE1C,MAAM,MAAM,2BAA2B,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9E,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxB;AAED,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,sBAAsB,CAAC,CA2BjC;AAED,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,2BAA2B,CAAC,CAmBtC;AAED,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,OAAO,CAAC,CAQlB"}
|
package/dist/idempotency-key.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { cacheValkeyClient } from "./clients.mjs";
|
|
3
|
+
import { unlinkIfValueMatches } from "./conditional.mjs";
|
|
3
4
|
import { loadScript, registerScript } from "./scripts.mjs";
|
|
5
|
+
import { stringifyValkeyResult } from "./valkey-result.mjs";
|
|
4
6
|
import { Decoder } from "@valkey/valkey-glide";
|
|
5
7
|
const DEFAULT_PROCESSING_PREFIX = "processing";
|
|
6
8
|
const DEFAULT_COMPLETED_VALUE = "completed";
|
|
@@ -10,7 +12,6 @@ const CHANGED_RESULT = "changed";
|
|
|
10
12
|
const SCRIPT_RESULT_VALUES = new Set([RESERVED_RESULT, MISSING_RESULT, CHANGED_RESULT]);
|
|
11
13
|
const idempotencyKeyReserveScript = registerScript(loadScript("idempotency-key-reserve.lua", import.meta.url));
|
|
12
14
|
const idempotencyKeyCompleteIfCurrentScript = registerScript(loadScript("idempotency-key-complete-if-current.lua", import.meta.url));
|
|
13
|
-
const idempotencyKeyReleaseIfCurrentScript = registerScript(loadScript("idempotency-key-release-if-current.lua", import.meta.url));
|
|
14
15
|
export async function getAndDelete(key, options = {}) {
|
|
15
16
|
validateKey(key);
|
|
16
17
|
const result = await (options.client ?? cacheValkeyClient).customCommand(["GETDEL", key], {
|
|
@@ -22,13 +23,23 @@ export async function getAndDelete(key, options = {}) {
|
|
|
22
23
|
}
|
|
23
24
|
export async function reserveIdempotencyKey(key, ttlSeconds, options = {}) {
|
|
24
25
|
validateKey(key);
|
|
25
|
-
validateTtlSeconds(ttlSeconds);
|
|
26
|
+
validateTtlSeconds("ttlSeconds", ttlSeconds);
|
|
26
27
|
const settings = normalizeIdempotencyOptions(options);
|
|
27
28
|
const token = options.token ?? randomUUID();
|
|
28
29
|
validateNonEmpty("token", token);
|
|
30
|
+
const repairMissingExpiry = options.repairMissingExpiry !== undefined;
|
|
31
|
+
const completedTtlSeconds = options.repairMissingExpiry?.completedTtlSeconds ?? ttlSeconds;
|
|
32
|
+
validateTtlSeconds("completedTtlSeconds", completedTtlSeconds);
|
|
29
33
|
const result = await settings.client.invokeScript(idempotencyKeyReserveScript, {
|
|
30
34
|
keys: [key],
|
|
31
|
-
args: [
|
|
35
|
+
args: [
|
|
36
|
+
String(ttlSeconds),
|
|
37
|
+
settings.processingPrefix,
|
|
38
|
+
settings.completedValue,
|
|
39
|
+
token,
|
|
40
|
+
repairMissingExpiry ? "1" : "0",
|
|
41
|
+
String(completedTtlSeconds),
|
|
42
|
+
],
|
|
32
43
|
decoder: Decoder.String,
|
|
33
44
|
});
|
|
34
45
|
if (result === RESERVED_RESULT)
|
|
@@ -42,7 +53,7 @@ export async function reserveIdempotencyKey(key, ttlSeconds, options = {}) {
|
|
|
42
53
|
export async function completeIdempotencyKey(key, token, ttlSeconds, options = {}) {
|
|
43
54
|
validateKey(key);
|
|
44
55
|
validateNonEmpty("token", token);
|
|
45
|
-
validateTtlSeconds(ttlSeconds);
|
|
56
|
+
validateTtlSeconds("ttlSeconds", ttlSeconds);
|
|
46
57
|
const settings = normalizeIdempotencyOptions(options);
|
|
47
58
|
const result = await settings.client.invokeScript(idempotencyKeyCompleteIfCurrentScript, {
|
|
48
59
|
keys: [key],
|
|
@@ -63,12 +74,9 @@ export async function releaseIdempotencyKey(key, token, options = {}) {
|
|
|
63
74
|
validateKey(key);
|
|
64
75
|
validateNonEmpty("token", token);
|
|
65
76
|
const settings = normalizeIdempotencyOptions(options);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
args: [processingValue(settings.processingPrefix, token)],
|
|
69
|
-
decoder: Decoder.String,
|
|
77
|
+
return await unlinkIfValueMatches(key, processingValue(settings.processingPrefix, token), {
|
|
78
|
+
client: settings.client,
|
|
70
79
|
});
|
|
71
|
-
return result === 1 || result === 1n;
|
|
72
80
|
}
|
|
73
81
|
function normalizeIdempotencyOptions(options) {
|
|
74
82
|
const processingPrefix = options.processingPrefix ?? DEFAULT_PROCESSING_PREFIX;
|
|
@@ -95,9 +103,11 @@ function processingValue(processingPrefix, token) {
|
|
|
95
103
|
function validateKey(key) {
|
|
96
104
|
validateNonEmpty("key", key);
|
|
97
105
|
}
|
|
98
|
-
function validateTtlSeconds(ttlSeconds) {
|
|
99
|
-
if (ttlSeconds
|
|
100
|
-
throw new Error(
|
|
106
|
+
function validateTtlSeconds(name, ttlSeconds) {
|
|
107
|
+
if (!(ttlSeconds > 0))
|
|
108
|
+
throw new Error(`${name} must be greater than 0`);
|
|
109
|
+
if (!Number.isSafeInteger(ttlSeconds))
|
|
110
|
+
throw new Error(`${name} must be a positive safe integer`);
|
|
101
111
|
}
|
|
102
112
|
function validateNonEmpty(name, value) {
|
|
103
113
|
if (!value)
|
|
@@ -108,12 +118,4 @@ function validateStoredStateValue(name, value) {
|
|
|
108
118
|
throw new Error(`${name} must not equal a script result sentinel`);
|
|
109
119
|
}
|
|
110
120
|
}
|
|
111
|
-
function stringifyValkeyResult(result) {
|
|
112
|
-
if (typeof result === "string")
|
|
113
|
-
return result;
|
|
114
|
-
if (typeof result === "number" || typeof result === "bigint" || typeof result === "boolean") {
|
|
115
|
-
return result.toString();
|
|
116
|
-
}
|
|
117
|
-
return JSON.stringify(result) ?? "[unserializable]";
|
|
118
|
-
}
|
|
119
121
|
//# sourceMappingURL=idempotency-key.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idempotency-key.mjs","sourceRoot":"","sources":["../idempotency-key.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAoB,MAAM,sBAAsB,CAAC;AAEjE,MAAM,yBAAyB,GAAG,YAAY,CAAC;AAC/C,MAAM,uBAAuB,GAAG,WAAW,CAAC;AAC5C,MAAM,eAAe,GAAG,UAAU,CAAC;AACnC,MAAM,cAAc,GAAG,SAAS,CAAC;AACjC,MAAM,cAAc,GAAG,SAAS,CAAC;AACjC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC;AAExF,MAAM,2BAA2B,GAAG,cAAc,CAChD,UAAU,CAAC,6BAA6B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAC3D,CAAC;AACF,MAAM,qCAAqC,GAAG,cAAc,CAC1D,UAAU,CAAC,yCAAyC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CACvE,CAAC;
|
|
1
|
+
{"version":3,"file":"idempotency-key.mjs","sourceRoot":"","sources":["../idempotency-key.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAoB,MAAM,sBAAsB,CAAC;AAEjE,MAAM,yBAAyB,GAAG,YAAY,CAAC;AAC/C,MAAM,uBAAuB,GAAG,WAAW,CAAC;AAC5C,MAAM,eAAe,GAAG,UAAU,CAAC;AACnC,MAAM,cAAc,GAAG,SAAS,CAAC;AACjC,MAAM,cAAc,GAAG,SAAS,CAAC;AACjC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC;AAExF,MAAM,2BAA2B,GAAG,cAAc,CAChD,UAAU,CAAC,6BAA6B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAC3D,CAAC;AACF,MAAM,qCAAqC,GAAG,cAAc,CAC1D,UAAU,CAAC,yCAAyC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CACvE,CAAC;AA+BF,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,UAA+B,EAAE;IAEjC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjB,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,iBAAiB,CAAC,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE;QACxF,OAAO,EAAE,OAAO,CAAC,MAAM;KACxB,CAAC,CAAC;IACH,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACpD,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAAW,EACX,UAAkB,EAClB,UAAwC,EAAE;IAE1C,WAAW,CAAC,GAAG,CAAC,CAAC;IACjB,kBAAkB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC;IAC5C,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACjC,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,KAAK,SAAS,CAAC;IACtE,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,EAAE,mBAAmB,IAAI,UAAU,CAAC;IAC3F,kBAAkB,CAAC,qBAAqB,EAAE,mBAAmB,CAAC,CAAC;IAE/D,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,2BAA2B,EAAE;QAC7E,IAAI,EAAE,CAAC,GAAG,CAAC;QACX,IAAI,EAAE;YACJ,MAAM,CAAC,UAAU,CAAC;YAClB,QAAQ,CAAC,gBAAgB;YACzB,QAAQ,CAAC,cAAc;YACvB,KAAK;YACL,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;YAC/B,MAAM,CAAC,mBAAmB,CAAC;SAC5B;QACD,OAAO,EAAE,OAAO,CAAC,MAAM;KACxB,CAAC,CAAC;IAEH,IAAI,MAAM,KAAK,eAAe;QAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IACpE,IAAI,MAAM,KAAK,QAAQ,CAAC,gBAAgB;QAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IACzE,IAAI,MAAM,KAAK,QAAQ,CAAC,cAAc;QAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IACtE,MAAM,IAAI,KAAK,CAAC,yCAAyC,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC5F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,GAAW,EACX,KAAa,EACb,UAAkB,EAClB,UAAiC,EAAE;IAEnC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjB,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACjC,kBAAkB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;IAEtD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,qCAAqC,EAAE;QACvF,IAAI,EAAE,CAAC,GAAG,CAAC;QACX,IAAI,EAAE;YACJ,MAAM,CAAC,UAAU,CAAC;YAClB,eAAe,CAAC,QAAQ,CAAC,gBAAgB,EAAE,KAAK,CAAC;YACjD,QAAQ,CAAC,cAAc;SACxB;QACD,OAAO,EAAE,OAAO,CAAC,MAAM;KACxB,CAAC,CAAC;IAEH,IAAI,MAAM,KAAK,QAAQ,CAAC,cAAc;QAAE,OAAO,WAAW,CAAC;IAC3D,IAAI,MAAM,KAAK,cAAc,IAAI,MAAM,KAAK,cAAc;QAAE,OAAO,MAAM,CAAC;IAC1E,MAAM,IAAI,KAAK,CAAC,4CAA4C,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,GAAW,EACX,KAAa,EACb,UAAiC,EAAE;IAEnC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjB,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;IAEtD,OAAO,MAAM,oBAAoB,CAAC,GAAG,EAAE,eAAe,CAAC,QAAQ,CAAC,gBAAgB,EAAE,KAAK,CAAC,EAAE;QACxF,MAAM,EAAE,QAAQ,CAAC,MAAM;KACxB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,2BAA2B,CAClC,OAA8B;IAE9B,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,yBAAyB,CAAC;IAC/E,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,uBAAuB,CAAC;IACzE,gBAAgB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IACvD,gBAAgB,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IACnD,wBAAwB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;IAC/D,wBAAwB,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IAC3D,IAAI,gBAAgB,KAAK,cAAc,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,cAAc,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,iBAAiB;QAC3C,gBAAgB;QAChB,cAAc;KACf,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,gBAAwB,EAAE,KAAa;IAC9D,OAAO,GAAG,gBAAgB,IAAI,KAAK,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAE,UAAkB;IAC1D,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,yBAAyB,CAAC,CAAC;IACzE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,kCAAkC,CAAC,CAAC;AACpG,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,KAAa;IACnD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,oBAAoB,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAY,EAAE,KAAa;IAC3D,IAAI,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,0CAA0C,CAAC,CAAC;IACrE,CAAC;AACH,CAAC"}
|
package/dist/index.d.mts
CHANGED
|
@@ -4,6 +4,7 @@ export * from "./cache.mts";
|
|
|
4
4
|
export * from "./bloom-filter.mts";
|
|
5
5
|
export * from "./dynamic-config.mts";
|
|
6
6
|
export * from "./idempotency-key.mts";
|
|
7
|
+
export * from "./conditional.mts";
|
|
7
8
|
export * from "./clients.mts";
|
|
8
9
|
export * from "./shutdown.mts";
|
|
9
10
|
export * from "./scripts.mts";
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../index.mts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,YAAY,EACV,oCAAoC,EACpC,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../index.mts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,YAAY,EACV,oCAAoC,EACpC,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
|
package/dist/index.mjs
CHANGED
|
@@ -4,6 +4,7 @@ export * from "./cache.mjs";
|
|
|
4
4
|
export * from "./bloom-filter.mjs";
|
|
5
5
|
export * from "./dynamic-config.mjs";
|
|
6
6
|
export * from "./idempotency-key.mjs";
|
|
7
|
+
export * from "./conditional.mjs";
|
|
7
8
|
export * from "./clients.mjs";
|
|
8
9
|
export * from "./shutdown.mjs";
|
|
9
10
|
export * from "./scripts.mjs";
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../index.mts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../index.mts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
--
|
|
1
|
+
-- Compatibility script for callers that load the historical idempotency-specific filename.
|
|
2
|
+
-- New code should use unlink-if-value-matches.lua through unlinkIfValueMatches().
|
|
2
3
|
-- KEYS[1] = idempotency key
|
|
3
4
|
-- ARGV[1] = expected processing value
|
|
4
5
|
-- Returns: 1 when released, 0 when absent or changed.
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
-- ARGV[2] = processing value prefix
|
|
5
5
|
-- ARGV[3] = completed value
|
|
6
6
|
-- ARGV[4] = reservation token
|
|
7
|
+
-- ARGV[5] = repair missing expiry (1 or 0)
|
|
8
|
+
-- ARGV[6] = completed ttl seconds
|
|
7
9
|
-- Returns: reserved | processing prefix | completed value
|
|
8
10
|
local ttl = tonumber(ARGV[1])
|
|
9
11
|
local processingPrefix = ARGV[2]
|
|
@@ -13,8 +15,32 @@ if ttl == nil or processingPrefix == nil or completedValue == nil or token == ni
|
|
|
13
15
|
error('idempotency-key-reserve: ttl, processing prefix, completed value, and token are required')
|
|
14
16
|
end
|
|
15
17
|
|
|
18
|
+
-- ARGV[5] and ARGV[6] were added after the original four-argument contract.
|
|
19
|
+
-- Default them so callers that load the packaged script directly remain compatible.
|
|
20
|
+
local repairMissingExpiry = ARGV[5] or '0'
|
|
21
|
+
local completedTtl = ttl
|
|
22
|
+
if ARGV[6] ~= nil then
|
|
23
|
+
completedTtl = tonumber(ARGV[6])
|
|
24
|
+
if completedTtl == nil then
|
|
25
|
+
error('idempotency-key-reserve: completed ttl must be a number')
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
if ttl <= 0 or completedTtl <= 0 then
|
|
29
|
+
error('idempotency-key-reserve: ttl and completed ttl must be positive')
|
|
30
|
+
end
|
|
31
|
+
if repairMissingExpiry ~= '0' and repairMissingExpiry ~= '1' then
|
|
32
|
+
error('idempotency-key-reserve: repair flag must be 0 or 1')
|
|
33
|
+
end
|
|
34
|
+
|
|
16
35
|
local existing = redis.call('GET', KEYS[1])
|
|
17
36
|
if existing then
|
|
37
|
+
if repairMissingExpiry == '1' then
|
|
38
|
+
if existing == completedValue then
|
|
39
|
+
redis.call('EXPIRE', KEYS[1], completedTtl, 'NX')
|
|
40
|
+
else
|
|
41
|
+
redis.call('EXPIRE', KEYS[1], ttl, 'NX')
|
|
42
|
+
end
|
|
43
|
+
end
|
|
18
44
|
if existing == completedValue then
|
|
19
45
|
return completedValue
|
|
20
46
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
-- Atomically unlink a key only when its stored value matches the expected value.
|
|
2
|
+
-- KEYS[1] = key
|
|
3
|
+
-- ARGV[1] = expected value
|
|
4
|
+
-- Returns: 1 when unlinked, 0 when absent or changed.
|
|
5
|
+
if ARGV[1] == nil then
|
|
6
|
+
error('unlink-if-value-matches: expected value is required')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
local existing = redis.call('GET', KEYS[1])
|
|
10
|
+
if existing and existing == ARGV[1] then
|
|
11
|
+
redis.call('UNLINK', KEYS[1])
|
|
12
|
+
return 1
|
|
13
|
+
end
|
|
14
|
+
return 0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"valkey-result.d.mts","sourceRoot":"","sources":["../valkey-result.mts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAM7D"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function stringifyValkeyResult(result) {
|
|
2
|
+
if (typeof result === "string")
|
|
3
|
+
return result;
|
|
4
|
+
if (typeof result === "number" || typeof result === "bigint" || typeof result === "boolean") {
|
|
5
|
+
return result.toString();
|
|
6
|
+
}
|
|
7
|
+
return JSON.stringify(result) ?? "[unserializable]";
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=valkey-result.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"valkey-result.mjs","sourceRoot":"","sources":["../valkey-result.mts"],"names":[],"mappings":"AAAA,MAAM,UAAU,qBAAqB,CAAC,MAAe;IACnD,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5F,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,kBAAkB,CAAC;AACtD,CAAC"}
|
package/docs/api.md
CHANGED
|
@@ -16,7 +16,7 @@ This is the entry point for the public `valkyries` API. Detailed API documentati
|
|
|
16
16
|
- [Events and metrics](events-and-metrics.md) - `valkeyEvents`, cache metrics, event payloads, and error handling hooks.
|
|
17
17
|
- [Lua scripts](lua-scripts.md) - packaged Lua scripts and script-loading helpers.
|
|
18
18
|
- [Configuration](configuration.md) - environment variables and connection behavior.
|
|
19
|
-
- [Utilities](utilities.md) - key
|
|
19
|
+
- [Utilities](utilities.md) - key and Valkey result normalization helpers.
|
|
20
20
|
|
|
21
21
|
## Package Entry Points
|
|
22
22
|
|
package/docs/cache.md
CHANGED
|
@@ -209,6 +209,19 @@ ValkeyCache.invalidate(prefix: string, client?: GlideClient): Promise<void>
|
|
|
209
209
|
|
|
210
210
|
Deletes every cache key for `prefix`. Passing an empty prefix invalidates all cache namespaces visible to the client.
|
|
211
211
|
|
|
212
|
+
## `ValkeyCache.invalidateMany(prefixes, client?)`
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
ValkeyCache.invalidateMany(
|
|
216
|
+
prefixes: readonly string[],
|
|
217
|
+
client?: GlideClient,
|
|
218
|
+
): Promise<void>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Deletes every cache key for the supplied prefixes with one cursor scan. Duplicate prefixes are
|
|
222
|
+
ignored, an empty list is a no-op, and an empty prefix invalidates all cache namespaces visible to
|
|
223
|
+
the client.
|
|
224
|
+
|
|
212
225
|
## `getKey(key)`
|
|
213
226
|
|
|
214
227
|
```ts
|
package/docs/clients.md
CHANGED
|
@@ -107,11 +107,3 @@ onGracefulShutdown(): Promise<void>
|
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
Both exports point to the same idempotent shutdown function. It closes all live dynamic configs, package-managed clients, and the dynamic-config subscription client.
|
|
110
|
-
|
|
111
|
-
## `deleteKeysWithPrefix(client, pattern)`
|
|
112
|
-
|
|
113
|
-
```ts
|
|
114
|
-
deleteKeysWithPrefix(client: GlideClient, pattern: string): Promise<void>
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
Scans keys matching `pattern` and unlinks them in batches. This helper is used by cache and rate-limiter invalidation APIs.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Conditional Operations
|
|
2
|
+
|
|
3
|
+
Generic single-key operations for application-owned Valkey values.
|
|
4
|
+
|
|
5
|
+
## `unlinkIfValueMatches(key, expectedValue, options?)`
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
unlinkIfValueMatches(
|
|
9
|
+
key: string,
|
|
10
|
+
expectedValue: string,
|
|
11
|
+
options?: { client?: GlideClient },
|
|
12
|
+
): Promise<boolean>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Atomically reads and unlinks one key using a Lua script.
|
|
16
|
+
|
|
17
|
+
- Returns `true` only when the stored string matched `expectedValue` and was unlinked.
|
|
18
|
+
- Returns `false` when the key is absent or its value changed.
|
|
19
|
+
- Accepts an empty expected value, but the key must be non-empty.
|
|
20
|
+
- Throws Valkey/client errors and unexpected script responses.
|
|
21
|
+
- Defaults to the package cache client.
|
|
22
|
+
|
|
23
|
+
The helper is single-key and Redis Cluster safe. Callers own key naming and any hash tags needed
|
|
24
|
+
to colocate this key with other application operations.
|
package/docs/idempotency-key.md
CHANGED
|
@@ -26,6 +26,9 @@ reserveIdempotencyKey(
|
|
|
26
26
|
processingPrefix?: string;
|
|
27
27
|
completedValue?: string;
|
|
28
28
|
token?: string;
|
|
29
|
+
repairMissingExpiry?: {
|
|
30
|
+
completedTtlSeconds?: number;
|
|
31
|
+
};
|
|
29
32
|
},
|
|
30
33
|
): Promise<
|
|
31
34
|
| { state: "reserved"; token: string }
|
|
@@ -38,6 +41,10 @@ Atomically reserves a key when it is absent by storing `processing:<token>` with
|
|
|
38
41
|
- Generates a random token by default.
|
|
39
42
|
- Returns `processing` when another reservation is active.
|
|
40
43
|
- Returns `completed` when the dedup key has already completed.
|
|
44
|
+
- When `repairMissingExpiry` is present, persistent existing processing values receive
|
|
45
|
+
`ttlSeconds` and persistent completed values receive `completedTtlSeconds`.
|
|
46
|
+
- `completedTtlSeconds` defaults to `ttlSeconds`; `EXPIRE ... NX` preserves existing expirations.
|
|
47
|
+
- Missing-expiry repair is disabled by default.
|
|
41
48
|
- The caller owns key naming and Redis Cluster hash tags.
|
|
42
49
|
|
|
43
50
|
## `completeIdempotencyKey(key, token, ttlSeconds, options?)`
|
|
@@ -53,10 +60,14 @@ completeIdempotencyKey(
|
|
|
53
60
|
|
|
54
61
|
Atomically changes `processing:<token>` to `completed` with `EX ttlSeconds`.
|
|
55
62
|
|
|
56
|
-
- `completed`:
|
|
63
|
+
- `completed`: completion is recorded, including when the key was already completed.
|
|
57
64
|
- `missing`: the key was absent.
|
|
58
65
|
- `changed`: the key existed but did not match the caller's token.
|
|
59
66
|
|
|
67
|
+
Completed values do not retain their reservation token, so an already-completed result cannot
|
|
68
|
+
prove which owner originally completed it. Treating that result as success makes completion safe
|
|
69
|
+
to retry after an ambiguous client or network failure.
|
|
70
|
+
|
|
60
71
|
## `releaseIdempotencyKey(key, token, options?)`
|
|
61
72
|
|
|
62
73
|
```ts
|
|
@@ -93,7 +104,7 @@ try {
|
|
|
93
104
|
## Validation
|
|
94
105
|
|
|
95
106
|
- `key`, `token`, `processingPrefix`, and `completedValue` must be non-empty.
|
|
96
|
-
- `ttlSeconds` must be
|
|
107
|
+
- `ttlSeconds` and `completedTtlSeconds` must be positive safe integers.
|
|
97
108
|
- `processingPrefix` must not equal `completedValue`.
|
|
98
109
|
- `processingPrefix` and `completedValue` must not equal script result sentinels:
|
|
99
110
|
`reserved`, `missing`, or `changed`.
|
package/docs/lua-scripts.md
CHANGED
|
@@ -48,9 +48,13 @@ Dynamic config scripts:
|
|
|
48
48
|
Idempotency key scripts:
|
|
49
49
|
|
|
50
50
|
- `idempotency-key-complete-if-current.lua`
|
|
51
|
-
- `idempotency-key-release-if-current.lua`
|
|
51
|
+
- `idempotency-key-release-if-current.lua` (compatibility filename; new code uses conditional unlink)
|
|
52
52
|
- `idempotency-key-reserve.lua`
|
|
53
53
|
|
|
54
|
+
Conditional operation scripts:
|
|
55
|
+
|
|
56
|
+
- `unlink-if-value-matches.lua`
|
|
57
|
+
|
|
54
58
|
Rate limiter scripts:
|
|
55
59
|
|
|
56
60
|
- `rate-limiter-add.lua`
|
package/docs/utilities.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Utilities
|
|
2
2
|
|
|
3
|
-
These helpers are exported from the package root
|
|
3
|
+
These normalization helpers are exported from the package root.
|
|
4
4
|
|
|
5
5
|
## `normalizeKey(key)`
|
|
6
6
|
|
|
@@ -25,41 +25,3 @@ normalizeCountResult(value: unknown): number
|
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
Normalizes numeric or bigint Valkey counts. Returns `0` for unexpected values.
|
|
28
|
-
|
|
29
|
-
## `ValkeyCacheTypeError`
|
|
30
|
-
|
|
31
|
-
```ts
|
|
32
|
-
class ValkeyCacheTypeError extends TypeError
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Thrown when a cache value does not match the configured mode.
|
|
36
|
-
|
|
37
|
-
## `serializeValue(value, mode)`
|
|
38
|
-
|
|
39
|
-
```ts
|
|
40
|
-
serializeValue(
|
|
41
|
-
value: unknown,
|
|
42
|
-
mode: "json" | "text" | "buffer",
|
|
43
|
-
): Promise<string | Buffer>
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Serializes values for cache storage and gzip-compresses payloads larger than 2 KiB.
|
|
47
|
-
|
|
48
|
-
## `decodeValue(result, mode)`
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
decodeValue(
|
|
52
|
-
result: GlideString | null,
|
|
53
|
-
mode: "json" | "text" | "buffer",
|
|
54
|
-
): Promise<string | Buffer | Record<string, unknown> | null>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
Decodes and decompresses cache values. Returns `null` for Valkey misses.
|
|
58
|
-
|
|
59
|
-
## `durationInMilliseconds(start)`
|
|
60
|
-
|
|
61
|
-
```ts
|
|
62
|
-
durationInMilliseconds(start: bigint): number
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Converts a `process.hrtime.bigint()` start timestamp to elapsed milliseconds.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "valkyries",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Valkey utilities for caches, bloom filters, dynamic configuration, and rate limiting.",
|
|
5
5
|
"homepage": "https://github.com/jonathanong/valkyries#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -32,6 +32,11 @@
|
|
|
32
32
|
"import": "./dist/cache.mjs",
|
|
33
33
|
"default": "./dist/cache.mjs"
|
|
34
34
|
},
|
|
35
|
+
"./conditional": {
|
|
36
|
+
"types": "./dist/conditional.d.mts",
|
|
37
|
+
"import": "./dist/conditional.mjs",
|
|
38
|
+
"default": "./dist/conditional.mjs"
|
|
39
|
+
},
|
|
35
40
|
"./bloom-filter": {
|
|
36
41
|
"types": "./dist/bloom-filter.d.mts",
|
|
37
42
|
"import": "./dist/bloom-filter.mjs",
|
|
@@ -57,12 +62,12 @@
|
|
|
57
62
|
"@valkey/valkey-glide": "^2.4.0"
|
|
58
63
|
},
|
|
59
64
|
"devDependencies": {
|
|
60
|
-
"@types/node": "^
|
|
65
|
+
"@types/node": "^26.1.0",
|
|
61
66
|
"@vitest/coverage-v8": "^4.1.6",
|
|
62
67
|
"github-actionlint": "^1.7.12",
|
|
63
|
-
"oxfmt": "^0.
|
|
68
|
+
"oxfmt": "^0.57.0",
|
|
64
69
|
"oxlint": "^1.65.0",
|
|
65
|
-
"oxlint-tsgolint": "^0.
|
|
70
|
+
"oxlint-tsgolint": "^0.24.0",
|
|
66
71
|
"tsx": "^4.22.1",
|
|
67
72
|
"typescript": "^6.0.3",
|
|
68
73
|
"vitest": "^4.1.6"
|