valkey-glide - feat: Add Valkey GLIDE storage adapter - #2146
EmilBuszylo wants to merge 3 commits into
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
All alerts resolved. Learn more about Socket for GitHub. This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored. |
7015207 to
505b4eb
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2146 +/- ##
===========================================
- Coverage 100.00% 99.49% -0.51%
===========================================
Files 55 56 +1
Lines 5281 5535 +254
Branches 857 922 +65
===========================================
+ Hits 5281 5507 +226
- Misses 0 28 +28 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@EmilBuszylo - thanks for doing the work on this. Here is what we need to do before we merge this Blocking
Requested, non-blocking
|
There was a problem hiding this comment.
AIKIDO-2026-115254 in protobufjs - low severity
protobufjs parses and decodes protobuf, ProtoJSON, and Text Format input across its decoder, reader, and wrapper code paths. Crafted input can drive unbounded recursion when converting nested Any values from objects, force conversion of oversized integer literals through BigInt, and let length-delimited fields decode past their declared boundaries. Processing such malformed or hostile input can exhaust the call stack, consume excessive CPU and memory, or misparse fields across message boundaries, degrading or crashing the affected process. The fix caps Any.fromObject recursion, bounds integer literals before BigInt conversion, and enforces declared field lengths while decoding.
Details
Remediation Aikido suggests bumping this package to version 8.8.0 to resolve this issue
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info
|
Hi @jaredwray — just a gentle nudge on this one. I've addressed all the review feedback from the previous round (batching for setMany/deleteMany/hasMany via GLIDE Batch/ClusterBatch, the clear()/iterator() namespace-prefix bug including glob-metacharacter escaping, streaming SCAN pages, the single-error-emit fix, Buffer pass-through, hardened URI parsing, and the README/dependency-range items), and coverage is now at 100% (statements/branches/functions/lines). The branch is kept in sync with main (no conflicts as of the latest push). Happy to make any further changes if something still needs adjusting — whenever you have a moment for another look, thank you! |
Adds @keyv/valkey-glide so Keyv can use the official GLIDE client, including AZ affinity and cluster-aware multi-key commands (jaredwray#1566). Co-authored-by: Cursor <cursoragent@cursor.com>
Blocking:
- setMany/deleteMany/hasMany now use one GLIDE Batch/ClusterBatch exec
instead of Promise.all per key, staying under the in-flight limit and
working across cluster slots (verified against a live cluster).
- clear() now scans "<prefix>:*" instead of "<prefix>*", so a namespace
no longer wipes another namespace that shares its prefix.
- iterator() and clear() stream per SCAN page (one MGET/UNLINK per page)
instead of collecting every key before a single giant call.
- Raised test coverage to 100% statements/branches/functions/lines and
added cluster-mode tests for scan, useSets, and the
{cluster: true, addresses} constructor path.
- pnpm-workspace.yaml: allowBuilds for @valkey/valkey-glide and
protobufjs set to false.
Non-blocking:
- Tightened the @valkey/valkey-glide dependency range to ^2.5.2.
- README: documented GLIDE's default timeouts/in-flight limit and how
to override them, platform support, and reworded the useSets caveat
now that it's confirmed non-atomic rather than cluster-unsafe.
- createClient() is now the single place that emits "error" on a
connect failure; set()/setMany() no longer double-emit.
- Removed the synchronous connect emit in the constructor (no listener
could ever observe it).
- toGlideValue passes Buffer through instead of stringifying it, so
binary values are no longer corrupted before being stored.
- hasMany batches EXISTS instead of fetching full values via getMany.
- parseConnectionUri tolerates malformed percent-encoding and no longer
sends an empty password when a URI has a bare username.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
clear() and iterator() build their SCAN MATCH pattern from the raw namespace, so a namespace containing *, ?, [, ], or \ was treated as glob syntax and could match a different namespace (e.g. "tenant*" would also match "tenant-prod"). Route both through a new getKeyPattern() that escapes those characters before appending the :* separator, mirroring the fix already shipped for @keyv/valkey (jaredwray#2147). Also documents that a namespace extending another with ":" (e.g. "users:archive" under "users") still can't be told apart from a key containing ":" — use useSets: true for that separation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
4ce0e2c to
e8d7c92
Compare
Adds
@keyv/valkey-glideso Keyv can use the official Valkey GLIDE Node client (@valkey/valkey-glide). This is the path discussed in #1566: keep@keyv/valkeyoniovalkey, and land GLIDE as a separate storage adapter.Please check if the PR fulfills these requirements
What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Feature: new official storage adapter
@keyv/valkey-glide.Why
GLIDE is the Valkey client with a Rust core, cluster-aware multi-key commands (
MGET,UNLINK, …), and read strategies including AZ affinity (readFrom+clientAz). That is not a drop-in foriovalkey, so a dedicated package matches the maintainer note on #1566.What
storage/valkey-glideimplementing the v6KeyvStorageAdaptercontract (expiresviaSET+PXAT).GlideClient.createClient/GlideClusterClient.createClientare async; the first command orgetClient()opens the connection. Existing GLIDE clients can be passed in.redis://,rediss://,valkey://,valkeys://), a GLIDE config object (cluster,addresses,readFrom,clientAz,useTLS, …), or an existing client.getManyuses GLIDEmget(cluster-aware).clear()/iterator()useSCAN(clusterClusterScanCursorwhen needed).useSetskey layout as@keyv/valkey.useSets: trueis documented as not cluster-safe.keyvREADME, website adapter overview.AZ affinity example: