Skip to content

fix(client): pass type mapping through zScan#3277

Open
raashish1601 wants to merge 1 commit into
redis:masterfrom
raashish1601:codex/2370-scan-iterator-type-mapping
Open

fix(client): pass type mapping through zScan#3277
raashish1601 wants to merge 1 commit into
redis:masterfrom
raashish1601:codex/2370-scan-iterator-type-mapping

Conversation

@raashish1601
Copy link
Copy Markdown
Contributor

@raashish1601 raashish1601 commented May 17, 2026

Summary

  • pass typeMapping through ZSCAN sorted-set reply transformation
  • stop scan iterators by cursor value so Buffer-mapped cursors terminate correctly
  • add a focused ZSCAN regression for RESP_TYPES.DOUBLE
  • add scan iterator coverage for withTypeMapping({ [RESP_TYPES.BLOB_STRING]: Buffer })

Closes #2370

Validation

  • node --import tsx -e "const assert = require(''node:assert/strict''); const ZSCAN = require(''./packages/client/lib/commands/ZSCAN.ts'').default; const { RESP_TYPES } = require(''./packages/client/lib/RESP/decoder.ts''); assert.deepEqual(ZSCAN.transformReply([''0'', [''member'', ''1.5'']], undefined, { [RESP_TYPES.DOUBLE]: String }), { cursor: ''0'', members: [{ value: ''member'', score: ''1.5'' }] }); assert.equal(Buffer.from(''0'').toString(), ''0''); console.log(''scan type mapping checks ok'');"
  • npm run lint:changed
  • npm run build

Redis-backed iterator tests were not run locally because Docker is not installed in this environment.


Note

Low Risk
Low-risk bugfixes to reply transformation and iterator cursor handling; main risk is subtle behavior change in scan loop termination when cursors are non-strings under type mapping/RESP3.

Overview
Ensures ZSCAN.transformReply forwards typeMapping into the sorted-set reply transformer so mapped DOUBLE scores (e.g. to String) are honored.

Updates all scan iterators (scanIterator, hScanIterator, hScanNoValuesIterator, sScanIterator, zScanIterator) to compare cursors via cursor.toString() so iteration terminates correctly even when cursors are returned as non-strings under type mapping.

Adds regression tests covering ZSCAN type-mapped scores and end-to-end iterator behavior with withTypeMapping (Blob strings as Buffer, doubles as String).

Reviewed by Cursor Bugbot for commit 784e02c. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread packages/client/lib/client/index.spec.ts
@raashish1601 raashish1601 force-pushed the codex/2370-scan-iterator-type-mapping branch from 6be35de to 784e02c Compare May 17, 2026 06:10
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 784e02c. Configure here.

sortedSetMembers.set(value.toString(), score);
}
}
assert.deepEqual(sortedSetMembers, new Map([['member', '1.5']]));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test asserts string score but gets Buffer

Medium Severity

The zScanIterator section of this test combines BLOB_STRING: Buffer and DOUBLE: String type mappings, then asserts the score equals the string '1.5'. In RESP2 (the default), scores arrive as blob strings, so the decoder converts them to Buffer via the BLOB_STRING: Buffer mapping. When transformDoubleReply[2] then processes this with DOUBLE: String, its case String branch returns the reply as-is — which is already a Buffer, not a string. The assert.deepEqual against new Map([['member', '1.5']]) would fail because the actual score is Buffer.from('1.5'). This test was never run against a real Redis server per the PR description.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 784e02c. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add option returnBuffers=true to the various ScanIterators

1 participant