Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ a low-latency, memory-efficient, distributed cache written in Rust. designed to
- **lru eviction** — approximate LRU via random sampling when memory pressure hits
- **persistence** — append-only file (AOF) and point-in-time snapshots
- **pipelining** — multiple commands per read for high throughput
- **interactive CLI** — `ember-cli` with REPL, tab-completion, inline help, and one-shot mode
- **interactive CLI** — `ember-cli` with REPL, syntax highlighting, tab-completion, inline hints, cluster subcommands, and built-in benchmark
- **graceful shutdown** — drains active connections on SIGINT/SIGTERM before exiting

## quickstart
Expand All @@ -61,7 +61,7 @@ cargo build --release
--tls-cert-file cert.pem --tls-key-file key.pem
```

ember speaks RESP3, so `redis-cli` works as a drop-in replacement — but `ember-cli` adds tab-completion, inline help, and auto-reconnect.
ember speaks RESP3, so `redis-cli` works as a drop-in replacement — but `ember-cli` adds syntax highlighting, tab-completion, inline hints, and auto-reconnect.

```bash
# ember-cli: interactive REPL with autocomplete and help
Expand All @@ -73,6 +73,14 @@ ember-cli -a mypassword # authenticate
ember-cli SET hello world # => OK
ember-cli GET hello # => "hello"

# cluster management subcommands
ember-cli cluster info # cluster state
ember-cli cluster nodes # list nodes
ember-cli cluster meet 10.0.0.1 6379

# built-in benchmark
ember-cli benchmark -n 100000 -c 50 -P 16

# redis-cli works too — same protocol, same port
redis-cli SET hello world # => OK
redis-cli GET hello # => "world"
Expand Down Expand Up @@ -172,7 +180,7 @@ crates/
ember-protocol/ RESP3 wire protocol
ember-persistence/ AOF and snapshot durability
ember-cluster/ raft consensus, gossip, slot management, migration
ember-cli/ interactive CLI client (REPL, one-shot, autocomplete)
ember-cli/ interactive CLI client (REPL, cluster subcommands, benchmark)
```

## architecture
Expand Down Expand Up @@ -227,7 +235,7 @@ contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).
| 4 | clustering (raft, gossip, slots, migration) | ✅ complete |
| 5 | developer experience (observability, CLI, clients) | 🚧 in progress |

**current**: 85 commands, 753 tests, ~14k lines of code (excluding tests)
**current**: 85 commands, 861 tests, ~18k lines of code (excluding tests)

## security

Expand Down
17 changes: 17 additions & 0 deletions bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,23 @@ KEY_COUNT=5000000 VALUE_SIZE=128 ./bench/bench-memory.sh
| `MEMTIER_REQUESTS` | 10000 | requests per client (480k total) |
| `MEMTIER_PIPELINE` | 16 | pipeline depth |

## built-in benchmark

ember also ships a built-in benchmark tool that doesn't require external dependencies:

```bash
# basic benchmark (100k requests, 50 clients)
ember-cli benchmark

# high-throughput with pipelining
ember-cli benchmark -n 1000000 -c 50 -P 16

# specific workloads
ember-cli benchmark -t set,get,ping -d 128
```

see `ember-cli benchmark --help` for all options.

## micro-benchmarks

for criterion micro-benchmarks:
Expand Down
74 changes: 73 additions & 1 deletion crates/ember-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,85 @@ ember-cli SET msg "hello world"

## repl features

- **tab completion** — press tab to autocomplete command names
- **tab completion** — press tab to autocomplete command names and subcommands
- **syntax highlighting** — known commands in cyan, unknown in red, quoted strings in green
- **inline hints** — shows argument synopsis and subcommand options as you type
- **history** — command history persisted to `~/.emberkv_history`
- **inline help** — type `help` for all commands, `help SET` for details
- **reconnection** — automatically reconnects if the server disconnects
- **quoted strings** — double and single quoted arguments with backslash escapes
- **timeouts** — 5s connect timeout, 10s read timeout to avoid hanging

## cluster subcommands

manage a cluster directly from the CLI without manually typing `CLUSTER` commands:

```bash
ember-cli cluster info
ember-cli cluster nodes
ember-cli cluster slots
ember-cli cluster keyslot mykey
ember-cli cluster myid
ember-cli cluster meet 10.0.0.1 6379
ember-cli cluster forget <node-id>
ember-cli cluster addslots 0 1 2 3
ember-cli cluster delslots 100 200
ember-cli cluster setslot 42 importing <node-id>
ember-cli cluster setslot 42 migrating <node-id>
ember-cli cluster setslot 42 node <node-id>
ember-cli cluster setslot 42 stable
ember-cli cluster replicate <node-id>
ember-cli cluster failover --force
ember-cli cluster failover --takeover
ember-cli cluster countkeysinslot 42
ember-cli cluster getkeysinslot 42 10
```

## built-in benchmark

run a built-in benchmark with pipelining support and latency percentile reporting:

```bash
# basic benchmark (100k requests, 50 clients)
ember-cli benchmark

# high-throughput test with pipelining
ember-cli benchmark -n 1000000 -c 50 -P 16

# test specific workloads
ember-cli benchmark -t set,get,ping

# customize data size and keyspace
ember-cli benchmark -d 128 --keyspace 1000000

# quiet mode — summary lines only
ember-cli benchmark -q
```

| flag | default | description |
|------|---------|-------------|
| `-n`, `--requests` | 100,000 | total number of requests |
| `-c`, `--clients` | 50 | concurrent client connections |
| `-P`, `--pipeline` | 1 | commands per pipeline batch |
| `-d`, `--data-size` | 64 | value payload size in bytes |
| `-t`, `--tests` | set,get | comma-separated workloads (`set`, `get`, `ping`) |
| `--keyspace` | 100,000 | number of unique keys |
| `-q`, `--quiet` | — | only print summary lines |

output:

```
=== ember benchmark ===
server: 127.0.0.1:6379
requests: 100,000
clients: 50
pipeline: 16
data size: 64 bytes

SET: 523,809 rps p50: 120us p99: 410us p99.9: 1.23ms max: 4.56ms
GET: 612,345 rps p50: 100us p99: 380us p99.9: 1.01ms max: 3.21ms
```

## local commands

these are handled by the client and not sent to the server:
Expand Down
2 changes: 1 addition & 1 deletion crates/ember-cluster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ the following CLUSTER commands are supported at the protocol layer:
| [ember-protocol](../ember-protocol) | RESP3 parsing and command dispatch |
| [ember-persistence](../ember-persistence) | AOF, snapshots, and crash recovery |
| [ember-server](../ember-server) | TCP server and connection handling |
| [ember-cli](../ember-cli) | interactive command-line client (planned) |
| [ember-cli](../ember-cli) | interactive CLI client (REPL, cluster subcommands, benchmark) |
2 changes: 1 addition & 1 deletion crates/ember-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ let response = engine.route("mykey", ShardRequest::Get {
| [ember-persistence](../ember-persistence) | AOF, snapshots, and crash recovery |
| [ember-server](../ember-server) | TCP server and connection handling |
| [ember-cluster](../ember-cluster) | distributed coordination |
| [ember-cli](../ember-cli) | interactive command-line client (planned) |
| [ember-cli](../ember-cli) | interactive CLI client (REPL, cluster subcommands, benchmark) |
2 changes: 1 addition & 1 deletion crates/ember-persistence/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ for entry in result.entries {
| [ember-protocol](../ember-protocol) | RESP3 parsing and command dispatch |
| [ember-server](../ember-server) | TCP server and connection handling |
| [ember-cluster](../ember-cluster) | distributed coordination |
| [ember-cli](../ember-cli) | interactive command-line client (planned) |
| [ember-cli](../ember-cli) | interactive CLI client (REPL, cluster subcommands, benchmark) |
2 changes: 1 addition & 1 deletion crates/ember-protocol/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ let cmd = Command::from_frame(frame).unwrap();
| [ember-persistence](../ember-persistence) | AOF, snapshots, and crash recovery |
| [ember-server](../ember-server) | TCP server and connection handling |
| [ember-cluster](../ember-cluster) | distributed coordination |
| [ember-cli](../ember-cli) | interactive command-line client (planned) |
| [ember-cli](../ember-cli) | interactive CLI client (REPL, cluster subcommands, benchmark) |
2 changes: 1 addition & 1 deletion crates/ember-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ compatible with `redis-cli` and any RESP3 client.
| [ember-protocol](../ember-protocol) | RESP3 parsing and command dispatch |
| [ember-persistence](../ember-persistence) | AOF, snapshots, and crash recovery |
| [ember-cluster](../ember-cluster) | distributed coordination |
| [ember-cli](../ember-cli) | interactive command-line client (planned) |
| [ember-cli](../ember-cli) | interactive CLI client (REPL, cluster subcommands, benchmark) |