Skip to content

Support RESP3 replies in redis.setresp(3) - #22

Merged
fatal10110 merged 6 commits into
mainfrom
codex/issue-9-resp3-setresp
Jun 30, 2026
Merged

Support RESP3 replies in redis.setresp(3)#22
fatal10110 merged 6 commits into
mainfrom
codex/issue-9-resp3-setresp

Conversation

@fatal10110

@fatal10110 fatal10110 commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add RESP3 ABI tags and TypeScript ReplyValue shapes for booleans, doubles, maps, sets, big numbers, and verbatim strings.
  • Make redis.setresp(3) enable RESP3 Lua conversions for the current script instead of rejecting it.
  • Decode RESP3 host replies for redis.call / redis.pcall, and document the expanded ABI.
  • Clarify that RESP3 push frames are not a Lua return type; they are server-initiated transport messages outside this script-engine surface.

Root Cause

redis.setresp(3) updated a protocol flag, but neither the C return encoder, host reply decoder, TypeScript codec, nor public ReplyValue type could represent RESP3 values. The first PR draft avoided the silent no-op by rejecting RESP3; this update implements the missing representable RESP3 shapes instead.

Real Redis Lua scripts can switch command reply conversion with redis.setresp(3), but push replies are not ordinary values returned by redis.call or by the script itself. They are out-of-band server-to-client protocol frames, so this PR models the RESP3 value types scripts can actually consume/return and documents push as out of scope.

Validation

  • Red before fix: node --test --import tsx --test-name-pattern "redis\\.setresp" test/engine.test.ts failed because RESP3 conversions were not represented.
  • Red before fix: node --test --import tsx --test-name-pattern "RESP3 values roundtrip" test/codec.test.ts failed because RESP3 values fell through to bulk encoding.
  • node --test --import tsx --test-name-pattern "redis\\.setresp|RESP3 values roundtrip" test/engine.test.ts test/codec.test.ts passed: 5/5.
  • npm run build passed.
  • npm test passed: 175/175.
  • Docs-only follow-up: clarified docs/limits-compat.md wording for RESP3 push scope.

Fixes #9

@fatal10110 fatal10110 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

RESP3 support looks solid and symmetric across the C encoder, C/TS decoders, and the type surface. The idx absolutization in encode_table correctly accounts for the new lua_getfield probes. Two minor findings below.

Comment thread src/codec.ts
}

if (type === REPLY_BIG_NUMBER) {
const payload = buffer.subarray(cursor, cursor + countOrLen);

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

REPLY_BIG_NUMBER decode skips the bounds check that every sibling RESP3 decoder here performs (BOOL/DOUBLE/VERBATIM all throw new Error("ERR reply decoding failed")), and that the C decoder does too (*offset + count_or_len > len). On a truncated/malformed buffer, buffer.subarray(cursor, cursor + countOrLen) silently clamps and you get a short big_number instead of an error. Add:

if (cursor + countOrLen > buffer.length) {
  throw new Error("ERR reply decoding failed");
}

Comment thread wasm/src/redis_api.c
return 1;
uint32_t next = (uint32_t)luaL_checkinteger(L, 1);
if (next != 2 && next != 3) {
return luaL_error(L, "ERR RESP version must be 2 or 3.");

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Redis's redis.setresp raises "RESP version must be 2 or 3." with no ERR prefix (src/script_lua.c luaSetResp). The added "ERR " here yields a spurious ERR code, deviating from the Redis-7 error fidelity the project targets. Drop the prefix to match.

@fatal10110 fatal10110 changed the title Reject unsupported redis.setresp versions Support RESP3 replies in redis.setresp(3) Jun 30, 2026
@fatal10110
fatal10110 marked this pull request as ready for review June 30, 2026 08:41
fatal10110 and others added 2 commits June 30, 2026 11:41
decodeReply skipped the length check the sibling RESP3 decoders
(BOOL/DOUBLE/VERBATIM) and the C decoder perform, so a truncated
big_number silently produced a short payload instead of throwing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@fatal10110

Copy link
Copy Markdown
Owner Author

Correction on my earlier review: the second finding (drop the ERR prefix from redis.setresp's error) was wrong — retracted. The codec splits the leading [A-Z][A-Z0-9]* token as code, so without ERR the message "RESP version must be 2 or 3." would parse RESP as the code and mangle the message. The ERR prefix correctly yields code=ERR + the Redis message body, matching how real Redis surfaces the error to clients. No change there.

The first finding (big-number bounds check) is fixed in e07e4c1.

@fatal10110
fatal10110 merged commit 837bdcd into main Jun 30, 2026
5 checks passed
@fatal10110
fatal10110 deleted the codex/issue-9-resp3-setresp branch June 30, 2026 08:54
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.

redis.setresp(3) accepted but has no effect (no RESP3 conversions)

1 participant