Skip to content

Redis 8.12 BLESS (eviction protection) support - #3261

Open
mgravell wants to merge 5 commits into
mainfrom
marc/bless
Open

mgravell wants to merge 5 commits into
mainfrom
marc/bless

Conversation

@mgravell

@mgravell mgravell commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Adds client support for the Redis 8.12 BLESS command family (redis/redis#15649), gated behind SER011 (Server_8_12).

API

[Flags] public enum BlessFlags { None = 0, NoEvict = 1 }

// IDatabase / IDatabaseAsync
bool       KeyBless(RedisKey key, BlessFlags bless, CommandFlags flags = CommandFlags.None);   // BLESS SET
bool       KeyUnbless(RedisKey key, BlessFlags bless, CommandFlags flags = CommandFlags.None); // BLESS CLEAR
BlessFlags KeyBlessFlags(RedisKey key, CommandFlags flags = CommandFlags.None);                // BLESS GET

// IServer
IEnumerable<RedisKey> BlessedKeys(BlessFlags bless, int database = -1, int pageSize = 250, long cursor = 0, int pageOffset = 0, CommandFlags flags = CommandFlags.None); // BLESS SCAN

Also: RedisFeatures.Bless, and KeyNotificationType.Bless / Unbless for the bless / unbless keyspace events (class g). After merging main post-#3312 these sit at 66/67, after the SetBit..SDiffStore range that PR added, and both tokens are in the parser test table.

Notes

  • BLESS is replica-eligible, so GET can be served by a replica; SET/CLEAR are raised to primary-only per message.
  • Retry: SET/CLEAR are write-checked (the flag state converges), GET is read-only, SCAN uses the usual cursor rule.
  • BlessFlags.None and undefined bits throw client-side. Unknown tokens in a GET reply are ignored.
  • BLESS SCAN always sends COUNT, because the server default (1024) isn't our page size.
  • BLESS is excluded from the Twemproxy and Envoy command maps.
  • Design notes and deviations from the cross-client HLD: redis-developer/client-designs redis-oss/client-hld/bless/se-redis.md.

Testing

  • Unit tests: result processor, exact wire bytes, routing/retry, key-prefix forwarding.
  • Live tests (require: v8_12_0) pass on RESP2 and RESP3 against redislabs/client-libs-test:8.12-m02-int.
  • 8.12 RC2 (2026-11-03): all Bless tests (live, round-trip, processor, key-prefix) pass against redislabs/client-libs-test:8.12-rc2. The NO-EVICT token, BLESS SCAN argument order, the missing-key no such key errors and the bless/unbless keyspace events were all re-verified by hand on RC2 and match the implementation.

Resolved (was: open before marking ready)

  • RedisFeatures.v8_12_0 is now pinned to 8.11.241, which is what 8.12 RC2 reports — the 8.12.0 placeholder would indeed have made the live tests skip on RCs. The docker topology / CI default image is now redislabs/client-libs-test:8.12-rc2, with cluster-bus-port-protected-mode no added to the test cluster configs (RC2 introduces that check and otherwise refuses to start a plaintext cluster node).

RC2 ZSCAN duplicates (server behavior change, handled)

The only CI failures on the RC2 image are the 8 ScanTests.SortedSetScanLarge cases (all page sizes, RESP2+RESP3): a full ZSCAN iteration over a stable 2000-element sorted set returns 2001-2003 entries, with a few members duplicated. Reproduced with pure redis-cli against redislabs/client-libs-test:8.12-rc2 (deterministic per dataset; ZCARD is 2000, distinct members 2000), clean on redis:8.2, and HSCAN/SSCAN are unaffected — a ZSCAN behavior change in the 8.12 btree zset encoding, reported upstream as redis/redis#16158. SortedSetScanLarge now asserts the distinct member count, so CI is expected green; revisit if redis/redis#16158 is fixed before GA. Everything else was already green (6700+ tests).

Adds KeyBless/KeyUnbless/KeyBlessFlags (+async) on IDatabase and
IServer.BlessedKeys (+async) over BLESS SCAN, with the BlessFlags enum,
gated behind SER011 (Server_8_12). SET/CLEAR are raised to primary-only;
GET stays replica-eligible. Adds bless/unbless keyspace notification types.
Resolves the KeyNotificationType collision with #3312: Bless and Unbless
move from 54/55 to 66/67, after the merged SetBit..SDiffStore range, and
the bless/unbless tokens join the parser test table. Experiments.cs and
Directory.Build.props take main's retirement of SER010 and keep SER011.
… image

- RedisFeatures.v8_12_0 is now 8.11.241, which is what 8.12 RC2 reports
  (the earlier 8.12.0 placeholder made the gated tests skip on RC2);
  this resolves the open pre-release-version question in the PR
- the test topology image defaults to redislabs/client-libs-test:8.12-rc2
- the cluster configs opt out of the new cluster-bus-port-protected-mode
  check, which otherwise refuses to start a plaintext cluster node on RC2

Validated locally against the RC2 topology: all Bless tests (live, round
trip, processor, prefix) pass, the bless/unbless keyspace events are
emitted as wired, and the cluster forms cleanly.
The 8.12 btree zset encoding can return duplicate members even for an
unmodified key (redis/redis#16158; the SCAN contract allows it), so the
test now asserts the distinct member count instead of the raw count.
All 8 cases pass against the RC2 topology.

This branch has not been deployed

No deployments
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.

1 participant