From 9a9ecbcc2ca189787e91b09cf5c327a9c8ef7e2b Mon Sep 17 00:00:00 2001 From: Kacy Fortner Date: Thu, 26 Feb 2026 20:16:26 -0500 Subject: [PATCH 1/3] =?UTF-8?q?docs:=20accuracy=20pass=20=E2=80=94=20concu?= =?UTF-8?q?rrent=20mode=20removal=20+=20command=20parity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit update 5 markdown files to reflect the current state of the codebase: - changelog: replace "concurrent pipeline dispatch" with "parallel pipeline dispatch" (less ambiguous); remove the 0.2.x line about concurrent keyspace mode with dashmap (feature was removed in 0.4.8, keeping it as history is misleading) - architecture: bump command count reference 135+ → 150+; update footer to not pin the doc to the clustering milestone - bench/readme: bump dragonfly comparison count 135 → 150 - docs/migration-from-redis.md: command count header 135 → 150; mark 20 commands as ✓ across strings, lists, sets, sorted sets, hashes, keys, and server tables (getset, getdel, getex, msetnx, lmove, lmpop, smove, sintercard, zrandmember, zunion, zinter, zdiff, zmpop, hrandfield, wait, expireat, pexpireat, expiretime, pexpiretime, config rewrite); replace the "bit operations not planned" paragraph with a single line covering only bitfield/bitfield_ro; remove the getset → set key value get substitution from migration steps - docs/compatibility.md: setnx ✗ → ✓ with legacy alias note; add setex and psetex rows (also legacy aliases, present in migration guide but missing here) --- ARCHITECTURE.md | 4 ++-- CHANGELOG.md | 3 +-- bench/README.md | 2 +- docs/compatibility.md | 4 +++- docs/migration-from-redis.md | 45 ++++++++++++++++++------------------ 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 521de864..84ea8b8e 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -42,7 +42,7 @@ the routing api on `Engine` has five methods: | `send_to_shard(idx, req)` | direct shard access by index (SCAN) | | `dispatch_to_shard(idx, req)` | non-blocking dispatch returning a oneshot receiver | -all five data types and all 135+ commands are supported. +all five data types and all 150+ commands are supported. --- @@ -412,4 +412,4 @@ feature propagation: `ember-server` features flow down to `emberkv-core`, which --- -*updated to reflect the state of the codebase as of the clustering milestone.* +*updated to reflect the current state of the codebase.* diff --git a/CHANGELOG.md b/CHANGELOG.md index eeaea1f4..9c2af687 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,7 +94,7 @@ this is the "make it real" milestone. ember went from a single-node cache to a c - bincode for raft rpcs — smaller wire format than json - o(log n) sorted set rank via vec-based structure - incremental memory tracking — `grow_by` / `shrink_by` instead of full recompute -- concurrent pipeline dispatch for multi-core throughput +- parallel pipeline dispatch for multi-core throughput - `now_ms()` caching to avoid repeated syscalls in expiry checks ### fixes @@ -139,7 +139,6 @@ with the foundation solid, this milestone filled in everything that makes ember - `--shards` flag to tune the number of keyspace partitions - jemalloc as the global allocator - pipeline dispatch optimization — batched command processing -- concurrent keyspace mode with dashmap for read-heavy workloads - memory overhead reduction — keyspace entry footprint profiled and trimmed - memtier benchmark integration - bench-all.sh for running all benchmark suites in one pass diff --git a/bench/README.md b/bench/README.md index e658a320..38f26f11 100644 --- a/bench/README.md +++ b/bench/README.md @@ -50,7 +50,7 @@ tested on GCP c2-standard-8 (8 vCPU Intel Xeon @ 3.10GHz), Ubuntu 22.04. dragonfly in particular offers features ember simply doesn't have: -- full Redis API compatibility (200+ commands vs ember's ~135) +- full Redis API compatibility (200+ commands vs ember's ~150) - sophisticated memory management (dashtable for ~25% of Redis memory usage) - Lua scripting - fork-free snapshotting diff --git a/docs/compatibility.md b/docs/compatibility.md index 93018de0..6c785f47 100644 --- a/docs/compatibility.md +++ b/docs/compatibility.md @@ -30,7 +30,9 @@ Ember also exposes port `6379` by default, the same as Redis, so most default co | GETSET | ✓ | atomic get-and-set; deprecated in Redis 6.2 but supported | | GETDEL | ✓ | | | GETEX | ✓ | | -| SETNX | ✗ | use `SET key value NX` instead | +| SETNX | ✓ | legacy alias; prefer `SET key value NX` | +| SETEX | ✓ | legacy alias; prefer `SET key value EX seconds` | +| PSETEX | ✓ | legacy alias; prefer `SET key value PX millis` | | MSETNX | ✓ | | | SUBSTR | ✗ | deprecated; use GETRANGE instead | diff --git a/docs/migration-from-redis.md b/docs/migration-from-redis.md index b4a776fa..fdea0f67 100644 --- a/docs/migration-from-redis.md +++ b/docs/migration-from-redis.md @@ -15,7 +15,7 @@ Ember speaks RESP3, so the first thing to know is that your existing Redis clien ## command compatibility -Ember implements over 135 Redis commands. The tables below show what's supported, what's missing, and any behavioral differences worth knowing about. +Ember implements over 150 Redis commands. The tables below show what's supported, what's missing, and any behavioral differences worth knowing about. Legend: `✓` supported, `~` partial or with caveats, `✗` not supported. @@ -40,10 +40,10 @@ Legend: `✓` supported, `~` partial or with caveats, `✗` not supported. | SETEX | ✓ | legacy alias; prefer `SET key value EX seconds` | | PSETEX | ✓ | legacy alias; prefer `SET key value PX millis` | | SUBSTR | ✓ | alias for GETRANGE | -| GETSET | ✗ | use `SET key value GET` instead | -| GETDEL | ✗ | not implemented | -| GETEX | ✗ | not implemented | -| MSETNX | ✗ | not implemented | +| GETSET | ✓ | atomic get-and-set; deprecated in Redis 6.2 | +| GETDEL | ✓ | | +| GETEX | ✓ | | +| MSETNX | ✓ | | ### lists @@ -65,8 +65,8 @@ Legend: `✓` supported, `~` partial or with caveats, `✗` not supported. | BRPOP | ✓ | multi-key with timeout | | LPUSHX | ✗ | not implemented | | RPUSHX | ✗ | not implemented | -| LMOVE | ✗ | not implemented | -| LMPOP | ✗ | not implemented | +| LMOVE | ✓ | | +| LMPOP | ✓ | | | BLMOVE | ✗ | not implemented | ### sets @@ -88,8 +88,8 @@ Legend: `✓` supported, `~` partial or with caveats, `✗` not supported. | SRANDMEMBER | ✓ | optional count | | SPOP | ✓ | optional count | | SSCAN | ✓ | | -| SMOVE | ✗ | not implemented | -| SINTERCARD | ✗ | not implemented | +| SMOVE | ✓ | cross-shard moves are sequential (not atomic) | +| SINTERCARD | ✓ | optional LIMIT cap | ### sorted sets @@ -115,14 +115,14 @@ Legend: `✓` supported, `~` partial or with caveats, `✗` not supported. | ZLEXCOUNT | ✗ | not implemented | | BZPOPMIN | ✗ | not implemented | | BZPOPMAX | ✗ | not implemented | -| ZRANDMEMBER | ✗ | not implemented | +| ZRANDMEMBER | ✓ | optional count with WITHSCORES | | ZUNIONSTORE | ✗ | not implemented | | ZINTERSTORE | ✗ | not implemented | | ZDIFFSTORE | ✗ | not implemented | -| ZUNION | ✗ | not implemented | -| ZINTER | ✗ | not implemented | -| ZDIFF | ✗ | not implemented | -| ZMPOP | ✗ | not implemented | +| ZUNION | ✓ | | +| ZINTER | ✓ | | +| ZDIFF | ✓ | | +| ZMPOP | ✓ | | | ZMSCORE | ✗ | not implemented | ### hashes @@ -142,7 +142,7 @@ Legend: `✓` supported, `~` partial or with caveats, `✗` not supported. | HSCAN | ✓ | | | HMSET | ✗ | use HSET with multiple fields instead | | HINCRBYFLOAT | ✗ | not implemented | -| HRANDFIELD | ✗ | not implemented | +| HRANDFIELD | ✓ | optional count with WITHVALUES | ### keys @@ -171,11 +171,11 @@ Legend: `✓` supported, `~` partial or with caveats, `✗` not supported. | SWAPDB | ✗ | single database only | | DUMP | ✗ | not implemented | | RESTORE | ~ | supported for cluster MIGRATE only | -| WAIT | ✗ | not implemented | -| EXPIREAT | ✗ | not implemented | -| PEXPIREAT | ✗ | not implemented | -| EXPIRETIME | ✗ | not implemented | -| PEXPIRETIME | ✗ | not implemented | +| WAIT | ✓ | waits for replica acknowledgements | +| EXPIREAT | ✓ | | +| PEXPIREAT | ✓ | | +| EXPIRETIME | ✓ | | +| PEXPIRETIME | ✓ | | ### server @@ -191,7 +191,7 @@ Legend: `✓` supported, `~` partial or with caveats, `✗` not supported. | FLUSHDB | ✓ | ASYNC mode supported | | CONFIG GET | ✓ | glob pattern matching | | CONFIG SET | ✓ | mutable: slowlog-log-slower-than, slowlog-max-len | -| CONFIG REWRITE | ✗ | not implemented | +| CONFIG REWRITE | ✓ | flushes runtime config back to file | | CONFIG RESETSTAT | ✗ | not implemented | | SLOWLOG GET | ✓ | optional count argument | | SLOWLOG LEN | ✓ | | @@ -307,7 +307,7 @@ A few Redis command families are explicitly out of scope: - **lua scripting** — EVAL, EVALSHA, EVALRO, SCRIPT LOAD/EXISTS/FLUSH, FCALL, and the FUNCTION family. Lua scripting is an anti-goal. WASM-based extensions may come in a future release. - **streams** — XADD, XREAD, XRANGE, and the full Streams family. Ember focuses on caching workloads; use a dedicated stream store for this. -- **bit operations** — BITCOUNT, SETBIT, GETBIT, BITOP, BITPOS, BITFIELD. Not implemented yet, may be added later. +- **BITFIELD / BITFIELD_RO** — not planned; use application-level serialization if needed. - **geo** — GEOADD, GEOPOS, GEODIST, GEORADIUS, GEOSEARCH, GEOHASH, and variants. Not implemented. - **hyperloglog** — PFADD, PFCOUNT, PFMERGE. Not implemented. @@ -463,7 +463,6 @@ before anything else, check which commands your application uses. the compatibil common substitutions: -- `GETSET key value` → `SET key value GET` - `SETNX key value` → `SET key value NX` - `SETEX key seconds value` → `SET key value EX seconds` - `HMSET key field value ...` → `HSET key field value ...` From fe517ecaeaff45d2be19aa3f460cf0ec327c71bf Mon Sep 17 00:00:00 2001 From: Kacy Fortner Date: Thu, 26 Feb 2026 21:00:51 -0500 Subject: [PATCH 2/3] docs: remove status phase table, relocate stats to benchmarks section --- README.md | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 0a44c9b8..18995fbd 100644 --- a/README.md +++ b/README.md @@ -458,6 +458,8 @@ redis-benchmark, 64B values, P=16, 8 threads. take these comparisons with a grai ./bench/bench-all.sh # run everything ``` +**150+ commands, 1,200+ tests, ~25k lines of code** (~47k including tests and comments). see [bench/README.md](bench/README.md) for full methodology and results. + ## architecture ember uses a thread-per-core architecture with channel-based routing. each shard owns a partition of the keyspace with no cross-shard locking on the hot path. supports all data types and enables atomic multi-key operations. @@ -480,23 +482,6 @@ contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). | [changelog](CHANGELOG.md) | release history and phase summaries | | [security policy](SECURITY.md) | vulnerability reporting, deployment hardening | -## status - -| phase | description | status | -|-------|-------------|--------| -| 1 | foundation (protocol, engine, expiration) | ✅ complete | -| 2 | persistence (AOF, snapshots, recovery) | ✅ complete | -| 3 | data types (sorted sets, lists, hashes, sets) | ✅ complete | -| 4 | clustering (raft, gossip, slots, migration) | ✅ complete | -| 5 | developer experience (observability, CLI, clients) | 🚧 in progress | -| 6 | replication and high availability | ✅ complete | -| 7 | security hardening | ✅ complete | -| 8 | production gaps (transactions, blocking ops, config) | ✅ complete | - -phase 6 added leader/replica data streaming, `CLUSTER REPLICATE`, automatic failover via epoch-based elections, and `CLUSTER FAILOVER` for manual promotion. phase 7 added RESP key/value size limits and cluster transport HMAC-SHA256 auth. phase 8 filled critical production gaps: MULTI/EXEC/DISCARD transactions, BLPOP/BRPOP blocking list ops, CONFIG GET/SET, WATCH optimistic locking, CLIENT introspection, SSCAN/HSCAN/ZSCAN collection scanning, and ACL per-user access control. - -**current**: 150+ commands, 1,200+ tests, ~25k lines of code (~47k including tests and comments) - ## security see [SECURITY.md](SECURITY.md) for: From f6e219c0ba67ca56fb34e417e57f3d3c8273f630 Mon Sep 17 00:00:00 2001 From: Kacy Fortner Date: Thu, 26 Feb 2026 22:46:47 -0500 Subject: [PATCH 3/3] docs: update command count to 190+ across readme and architecture --- ARCHITECTURE.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 84ea8b8e..26fa46d9 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -42,7 +42,7 @@ the routing api on `Engine` has five methods: | `send_to_shard(idx, req)` | direct shard access by index (SCAN) | | `dispatch_to_shard(idx, req)` | non-blocking dispatch returning a oneshot receiver | -all five data types and all 150+ commands are supported. +all five data types and all 190+ commands are supported. --- diff --git a/README.md b/README.md index 18995fbd..c0fd8515 100644 --- a/README.md +++ b/README.md @@ -458,7 +458,7 @@ redis-benchmark, 64B values, P=16, 8 threads. take these comparisons with a grai ./bench/bench-all.sh # run everything ``` -**150+ commands, 1,200+ tests, ~25k lines of code** (~47k including tests and comments). see [bench/README.md](bench/README.md) for full methodology and results. +**190+ commands, 1,200+ tests, ~25k lines of code** (~47k including tests and comments). see [bench/README.md](bench/README.md) for full methodology and results. ## architecture