cache-manager - fix: use store.deleteMany in mdel instead of per-key delete loop - #1697
cache-manager - fix: use store.deleteMany in mdel instead of per-key delete loop#1697pavelmaksimov25 wants to merge 1 commit into
Conversation
…delete loop mget and mset already delegate to the Keyv store's getMany/setMany, so bulk-capable adapters issue a single native command. mdel still looped the key list calling store.delete(key) per key, costing one round-trip per key. Align it with the mset pattern: stores.map((store) => store.deleteMany(keys)). Keyv's deleteMany falls back internally for adapters without native support, so no fallback logic is needed here. nonBlocking behavior, the mdel event payload, and the return value are unchanged. Closes jaredwray#1696
01c1b6a to
9a7c30c
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a7c30c045
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for (const key of keys) { | ||
| promises.push(...stores.map(async (store) => store.delete(key))); | ||
| } | ||
| const promises = stores.map(async (store) => store.deleteMany(keys)); |
There was a problem hiding this comment.
Preserve empty-list behavior before bulk deletion
When keys is empty and the cache uses the documented @keyv/redis store, this now invokes its native deleteMany([]), which delegates to Redis DEL without any key arguments and is rejected by Redis. Previously the empty loop produced Promise.all([]) and resolved true; the new empty-list test only exercises Keyv's in-memory fallback, so it does not cover this adapter-specific regression. Return early for an empty array before dispatching to stores.
Useful? React with 👍 / 👎.
Closes #1696
Please check if the PR fulfills these requirements
What kind of change does this PR introduce?
Bug fix / performance — aligns
mdelwith the bulk patternmgetandmsetalready use.Problem
Since #1014,
mgetandmsetdelegate to the Keyv store'sgetMany/setMany, so bulk-capable adapters (e.g.@keyv/redis) issue a single native command.mdelwas left out: it looped the key list callingstore.delete(key)per key, costing one round-trip per key.For N keys across M stores that is N × M round-trips.
Change
Mirrors the
msetimplementation exactly:M round-trips regardless of key count. Keyv's
deleteManyfalls back internally for adapters without native multi-delete support, so no fallback logic is needed in cache-manager.Unchanged:
nonBlockingbehavior, themdelevent payload, thePromise<true>return value, and error handling.Tests
test/mdel.test.ts:deleteManyreceives the whole key arraydeleteManyper store in a two-store cachetruedeleteManyand asserttoHaveBeenCalledOnce(), matching the shape oftest/mset.test.tspnpm testinpackages/cache-manager: 17 files, 89 tests passing, coverage 100% statements / 100% branches / 100% functions / 100% lines. Lint and build clean.Docs
Added a line to the
mdelsection ofpackages/cache-manager/README.mdnoting that keys are deleted with a single bulk operation per store.Note on scope
#1014 also mentions
hasMany. cache-manager currently exposes nomhas, so adding one is a new feature rather than an alignment — left out of this PR.