valkyries 0.5.0 → 0.6.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
@@ -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)
@@ -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;mBAQ7C,iCAAiC;CA0BvD"}
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"}
@@ -1,6 +1,6 @@
1
1
  import { cacheValkeyClient } from "../clients.mjs";
2
2
  import { emitValkeyEvent } from "../events.mjs";
3
- import { deleteKeysWithPrefix } from "../delete.mjs";
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 deleteKeysWithPrefix(client, prefix ? `${CACHE_NAMESPACE}:${prefix}:*` : `${CACHE_NAMESPACE}:*`);
120
- emitValkeyEvent("cache:invalidate", { cacheName: prefix });
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,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EACL,eAAe,EACf,+BAA+B,EAC/B,iCAAiC,GAClC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAiBvD,MAAM,OAAO,kBAA+B,SAAQ,oBAAuB;IACzE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAS;QACvB,MAAM,cAAc,GAAa,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,uBAAuB;QACvB,0DAA0D;QAC1D,6EAA6E;QAC7E,oFAAoF;QACpF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;gBACxB,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAChC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACpC,gDAAgD;QAChD,MAAM,gBAAgB,GAAG,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,4BAA4B,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,iCAAiC,EAAE;YAC/E,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,gBAAgB,CAAC;YACxC,IAAI,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,+BAA+B,CAAC,CAAC;SACzE,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC3C,eAAe,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC;IACf,CAAC;IAES,KAAK,CAAC,qBAAqB,CAAC,GAAG,cAAwB;QAC/D,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,CAAC;QAClC,IAAI,GAAG,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAExB,uBAAuB;QACvB,oDAAoD;QACpD,mEAAmE;QACnE,wHAAwH;QACxH,gDAAgD;QAChD,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAS,GAAG,CAAC,CAAC;QACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjD,eAAe,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,UAAU;QACR,OAAO,kBAAkB,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC;IAQD,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAC3B,OAAkE;QAElE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwC,CAAC;QAC/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,cAAc,GAAa,EAAE,CAAC;YACpC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC7B,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;gBACpD,IAAI,UAAU,KAAK,IAAI;oBAAE,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC3D,CAAC;YACD,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAE1C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC7C,MAAM,eAAe,GAAG;gBACtB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,cAAc;aACf,CAAC;YACF,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,QAAQ,GAAsB,EAAE,CAAC;QACrC,MAAM,iBAAiB,GAAG,CAAC,OAAuC,EAAQ,EAAE;YAC1E,IAAI,YAAY,GAAG,CAAC,CAAC;YACrB,IAAI,UAAU,GAAG,KAAK,CAAC;YACvB,IAAI,OAAgB,CAAC;YAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC1B,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;oBAClC,YAAY,IAAI,MAAM,CAAC,KAAK,CAAC;gBAC/B,CAAC;qBAAM,IAAI,CAAC,UAAU,EAAE,CAAC;oBACvB,UAAU,GAAG,IAAI,CAAC;oBAClB,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;gBAC1B,CAAC;YACH,CAAC;YAED,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,OAAO,CAAC;YAChB,CAAC;YACD,OAAO,IAAI,YAAY,CAAC;QAC1B,CAAC,CAAC;QAEF,uBAAuB;QACvB,iGAAiG;QACjG,kGAAkG;QAClG,6EAA6E;QAC7E,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,kBAAkB,CAAC,iCAAiC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC9E,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEjB,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;gBAC3B,iBAAiB,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACtD,QAAQ,GAAG,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,iBAAiB,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,MAAM,GAAG,iBAAiB;QAChE,MAAM,oBAAoB,CACxB,MAAM,EACN,MAAM,CAAC,CAAC,CAAC,GAAG,eAAe,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,GAAG,eAAe,IAAI,CACnE,CAAC;QACF,eAAe,CAAC,kBAAkB,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,iCAAiC,CACpD,MAAoC,EACpC,OAAgC;QAEhC,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,gBAAgB,GAAa,EAAE,CAAC;QACtC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,KAAK,MAAM,aAAa,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;gBACjD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,qBAAqB,CAAC,aAAa,CAAC,CAAC,CAAC;gBACjE,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,4BAA4B,CAAC,aAAa,CAAC,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,iCAAiC,EAAE;YAC1E,IAAI,EAAE,CAAC,GAAG,SAAS,EAAE,GAAG,gBAAgB,CAAC;YACzC,IAAI,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,+BAA+B,CAAC,CAAC;SAC1E,CAAC,CAAC;QAEH,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,eAAe,CAAC,cAAc,EAAE;gBAC9B,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;gBAC7B,IAAI,EAAE,KAAK,CAAC,cAAc;aAC3B,CAAC,CAAC;QACL,CAAC;QACD,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;CACF"}
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,6BAA6B,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EACL,eAAe,EACf,+BAA+B,EAC/B,iCAAiC,GAClC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAiBvD,MAAM,OAAO,kBAA+B,SAAQ,oBAAuB;IACzE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAS;QACvB,MAAM,cAAc,GAAa,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,uBAAuB;QACvB,0DAA0D;QAC1D,6EAA6E;QAC7E,oFAAoF;QACpF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;gBACxB,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAChC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACpC,gDAAgD;QAChD,MAAM,gBAAgB,GAAG,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,4BAA4B,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,iCAAiC,EAAE;YAC/E,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,gBAAgB,CAAC;YACxC,IAAI,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,+BAA+B,CAAC,CAAC;SACzE,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC3C,eAAe,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC;IACf,CAAC;IAES,KAAK,CAAC,qBAAqB,CAAC,GAAG,cAAwB;QAC/D,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,CAAC;QAClC,IAAI,GAAG,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAExB,uBAAuB;QACvB,oDAAoD;QACpD,mEAAmE;QACnE,wHAAwH;QACxH,gDAAgD;QAChD,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAS,GAAG,CAAC,CAAC;QACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjD,eAAe,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,UAAU;QACR,OAAO,kBAAkB,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC;IAQD,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAC3B,OAAkE;QAElE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwC,CAAC;QAC/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,cAAc,GAAa,EAAE,CAAC;YACpC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC7B,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;gBACpD,IAAI,UAAU,KAAK,IAAI;oBAAE,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC3D,CAAC;YACD,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAE1C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC7C,MAAM,eAAe,GAAG;gBACtB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,cAAc;aACf,CAAC;YACF,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC9B,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,QAAQ,GAAsB,EAAE,CAAC;QACrC,MAAM,iBAAiB,GAAG,CAAC,OAAuC,EAAQ,EAAE;YAC1E,IAAI,YAAY,GAAG,CAAC,CAAC;YACrB,IAAI,UAAU,GAAG,KAAK,CAAC;YACvB,IAAI,OAAgB,CAAC;YAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC1B,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;oBAClC,YAAY,IAAI,MAAM,CAAC,KAAK,CAAC;gBAC/B,CAAC;qBAAM,IAAI,CAAC,UAAU,EAAE,CAAC;oBACvB,UAAU,GAAG,IAAI,CAAC;oBAClB,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;gBAC1B,CAAC;YACH,CAAC;YAED,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,OAAO,CAAC;YAChB,CAAC;YACD,OAAO,IAAI,YAAY,CAAC;QAC1B,CAAC,CAAC;QAEF,uBAAuB;QACvB,iGAAiG;QACjG,kGAAkG;QAClG,6EAA6E;QAC7E,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,kBAAkB,CAAC,iCAAiC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC9E,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEjB,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;gBAC3B,iBAAiB,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACtD,QAAQ,GAAG,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,iBAAiB,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,MAAM,GAAG,iBAAiB;QAChE,MAAM,kBAAkB,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,QAA2B,EAAE,MAAM,GAAG,iBAAiB;QACjF,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;QACF,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAExC,MAAM,6BAA6B,CACjC,MAAM,EACN,GAAG,eAAe,IAAI,EACtB,cAAc,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAC5B,MAAM,CAAC,CAAC,CAAC,GAAG,eAAe,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,eAAe,GAAG,CACjE,CACF,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;YACpC,eAAe,CAAC,kBAAkB,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,iCAAiC,CACpD,MAAoC,EACpC,OAAgC;QAEhC,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,gBAAgB,GAAa,EAAE,CAAC;QACtC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,KAAK,MAAM,aAAa,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;gBACjD,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,qBAAqB,CAAC,aAAa,CAAC,CAAC,CAAC;gBACjE,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,4BAA4B,CAAC,aAAa,CAAC,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,iCAAiC,EAAE;YAC1E,IAAI,EAAE,CAAC,GAAG,SAAS,EAAE,GAAG,gBAAgB,CAAC;YACzC,IAAI,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,+BAA+B,CAAC,CAAC;SAC1E,CAAC,CAAC;QAEH,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,eAAe,CAAC,cAAc,EAAE;gBAC9B,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;gBAC7B,IAAI,EAAE,KAAK,CAAC,cAAc;aAC3B,CAAC,CAAC;QACL,CAAC;QACD,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;CACF"}
@@ -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 const deleteKeysWithPrefix: (client: GlideClient, pattern: string) => Promise<void>;
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
@@ -1 +1 @@
1
- {"version":3,"file":"delete.d.mts","sourceRoot":"","sources":["../delete.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,eAAO,MAAM,oBAAoB,GAAU,QAAQ,WAAW,EAAE,SAAS,MAAM,KAAG,OAAO,CAAC,IAAI,CAmC7F,CAAC"}
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
- export const deleteKeysWithPrefix = async (client, pattern) => {
3
- const unlinkPromises = [];
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
- // GlideClient scan method signature: scan(cursor: string, options?: ScanOptions)
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
- // Attach a no-op catch to prevent unhandled rejection crashes if scan fails
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
@@ -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,oBAAoB,GAAG,KAAK,EAAE,MAAmB,EAAE,OAAe,EAAiB,EAAE;IAChG,MAAM,cAAc,GAAsB,EAAE,CAAC;IAE7C,IAAI,CAAC;QACH,IAAI,MAAM,GAAG,GAAG,CAAC;QAEjB,GAAG,CAAC;YACF,iFAAiF;YACjF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YAC7D,MAAM,GAAG,MAAM,CAAC,CAAC,CAAW,CAAC;YAC7B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAa,CAAC;YAEnC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,4EAA4E;gBAC5E,6EAA6E;gBAC7E,2DAA2D;gBAC3D,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC9B,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBACzB,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAEvB,4DAA4D;gBAC5D,IAAI,cAAc,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;oBACjC,MAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;oBAClC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC,QAAQ,MAAM,KAAK,GAAG,EAAE;QAEzB,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACvB,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC,CAAC"}
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":"AAGA,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAmBjE,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;CAChB,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,CAiBjC;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,CAYlB"}
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"}
@@ -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: [String(ttlSeconds), settings.processingPrefix, settings.completedValue, token],
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
- const result = await settings.client.invokeScript(idempotencyKeyReleaseIfCurrentScript, {
67
- keys: [key],
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 <= 0)
100
- throw new Error("ttlSeconds must be greater than 0");
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":"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"}
1
+ {"version":3,"file":"idempotency-key.mjs","sourceRoot":"","sources":["../idempotency-key.mts"],"names":[],"mappings":"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"}
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";
@@ -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";
@@ -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 +1 @@
1
- {"version":3,"file":"retry.d.mts","sourceRoot":"","sources":["../retry.mts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAI9D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGzD;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4FAA4F;IAC5F,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IAC1C;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,CAAC,CAAC,CAuBZ;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,CAAC,CAAC,CAOZ"}
1
+ {"version":3,"file":"retry.d.mts","sourceRoot":"","sources":["../retry.mts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAI9D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGzD;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4FAA4F;IAC5F,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IAC1C;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,CAAC,CAAC,CA8BZ;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,2BAA2B,GACpC,OAAO,CAAC,CAAC,CAAC,CAOZ"}
package/dist/retry.mjs CHANGED
@@ -55,7 +55,14 @@ export async function retryValkeyOperation(fn, options) {
55
55
  if (attempt < maxAttempts - 1) {
56
56
  const maxJitter = Math.floor(delayMs * 4);
57
57
  const waitMs = jitter && maxJitter > 0 ? delayMs + randomInt(maxJitter + 1) : delayMs;
58
- await new Promise((resolve) => setTimeout(resolve, waitMs));
58
+ // Unref the backoff timer: a pending retry is benign background work and must never
59
+ // keep a process (or, notably, a test-runner worker) alive on its own. During normal
60
+ // operation the process stays alive via other refed handles (e.g. the HTTP server); on
61
+ // shutdown, an unrefed retry correctly stops blocking exit instead of forcing a timeout.
62
+ await new Promise((resolve) => {
63
+ const timer = setTimeout(resolve, waitMs);
64
+ timer?.unref?.();
65
+ });
59
66
  }
60
67
  }
61
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"retry.mjs","sourceRoot":"","sources":["../retry.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;;GAGG;AACH,MAAM,kBAAkB,GAAG;IACzB,mCAAmC;IACnC,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;IACnB,4BAA4B;CAC7B,CAAC;AAEF,MAAM,kBAAkB,GAAG,mCAAmC,CAAC;AAE/D;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1B,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;AACpD,CAAC;AAgBD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAoB,EACpB,OAAqC;IAErC,MAAM,EACJ,QAAQ,GAAG,CAAC,EACZ,OAAO,GAAG,IAAI,EACd,WAAW,GAAG,sBAAsB,EACpC,MAAM,GAAG,KAAK,GACf,GAAG,OAAO,IAAI,EAAE,CAAC;IAClB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1C,IAAI,SAAkB,CAAC;IACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;YACrC,SAAS,GAAG,KAAK,CAAC;YAClB,IAAI,OAAO,GAAG,WAAW,GAAG,CAAC,EAAE,CAAC;gBAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;gBAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,SAAS,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;gBACtF,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,SAAS,CAAC;AAClB,CAAC;AAYD;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAClC,EAAoB,EACpB,OAAqC;IAErC,OAAO,oBAAoB,CAAC,EAAE,EAAE;QAC9B,QAAQ,EAAE,OAAO,EAAE,QAAQ;QAC3B,OAAO,EAAE,OAAO,EAAE,OAAO;QACzB,WAAW,EAAE,iBAAiB;QAC9B,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"retry.mjs","sourceRoot":"","sources":["../retry.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;;GAGG;AACH,MAAM,kBAAkB,GAAG;IACzB,mCAAmC;IACnC,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;IACnB,4BAA4B;CAC7B,CAAC;AAEF,MAAM,kBAAkB,GAAG,mCAAmC,CAAC;AAE/D;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1B,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;AACpD,CAAC;AAgBD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAoB,EACpB,OAAqC;IAErC,MAAM,EACJ,QAAQ,GAAG,CAAC,EACZ,OAAO,GAAG,IAAI,EACd,WAAW,GAAG,sBAAsB,EACpC,MAAM,GAAG,KAAK,GACf,GAAG,OAAO,IAAI,EAAE,CAAC;IAClB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1C,IAAI,SAAkB,CAAC;IACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;YACrC,SAAS,GAAG,KAAK,CAAC;YAClB,IAAI,OAAO,GAAG,WAAW,GAAG,CAAC,EAAE,CAAC;gBAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;gBAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,SAAS,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;gBACtF,oFAAoF;gBACpF,qFAAqF;gBACrF,uFAAuF;gBACvF,yFAAyF;gBACzF,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBAClC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;oBAC1C,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,SAAS,CAAC;AAClB,CAAC;AAYD;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAClC,EAAoB,EACpB,OAAqC;IAErC,OAAO,oBAAoB,CAAC,EAAE,EAAE;QAC9B,QAAQ,EAAE,OAAO,EAAE,QAAQ;QAC3B,OAAO,EAAE,OAAO,EAAE,OAAO;QACzB,WAAW,EAAE,iBAAiB;QAC9B,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;AACL,CAAC"}
@@ -1,4 +1,5 @@
1
- -- Release an idempotency reservation only if the caller still owns the token.
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,2 @@
1
+ export declare function stringifyValkeyResult(result: unknown): string;
2
+ //# sourceMappingURL=valkey-result.d.mts.map
@@ -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 normalization, cache serialization helpers, TTL/count normalization, and timing helpers.
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.
@@ -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`: the caller still owned the reservation and completion was recorded.
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 greater than `0`.
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`.
@@ -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 for applications that need the same normalization and serialization behavior as the built-in classes.
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.5.0",
3
+ "version": "0.6.1",
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": "^25.8.0",
65
+ "@types/node": "^26.1.0",
61
66
  "@vitest/coverage-v8": "^4.1.6",
62
67
  "github-actionlint": "^1.7.12",
63
- "oxfmt": "^0.52.0",
68
+ "oxfmt": "^0.57.0",
64
69
  "oxlint": "^1.65.0",
65
- "oxlint-tsgolint": "^0.23.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"