{"id":49080671,"url":"https://github.com/fgulde/redis-clone","last_synced_at":"2026-05-17T00:27:57.235Z","repository":{"id":349362481,"uuid":"1201591548","full_name":"fgulde/redis-clone","owner":"fgulde","description":"A Redis server clone built in C++23 with Asio, implementing the RESP2 protocol","archived":false,"fork":false,"pushed_at":"2026-04-28T23:42:54.000Z","size":1345,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-29T01:24:04.906Z","etag":null,"topics":["asio","cmake","codecrafters","cpp","networking","redis"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fgulde.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-04T22:12:28.000Z","updated_at":"2026-04-28T23:42:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/fgulde/redis-clone","commit_stats":null,"previous_names":["fgulde/redis-clone"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/fgulde/redis-clone","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fgulde%2Fredis-clone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fgulde%2Fredis-clone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fgulde%2Fredis-clone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fgulde%2Fredis-clone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fgulde","download_url":"https://codeload.github.com/fgulde/redis-clone/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fgulde%2Fredis-clone/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32479448,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"ssl_error","status_checked_at":"2026-04-30T13:12:06.837Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asio","cmake","codecrafters","cpp","networking","redis"],"created_at":"2026-04-20T13:04:54.749Z","updated_at":"2026-05-17T00:27:57.215Z","avatar_url":"https://github.com/fgulde.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Redis-Clone in C++\n\n![CI](https://github.com/fgulde/redis-clone/actions/workflows/ci.yml/badge.svg)\n![C++23](https://img.shields.io/badge/C%2B%2B-23-blue?logo=cplusplus)\n[![codecov](https://codecov.io/gh/fgulde/redis-clone/graph/badge.svg)](https://codecov.io/gh/fgulde/redis-clone)\n![Last Commit](https://img.shields.io/github/last-commit/fgulde/redis-clone)\n\nA Redis-compatible server built from scratch in **C++23**, exploring in-memory databases, async I/O, and concurrent systems programming.\n\n## Goal\n\nThis project reimplements core Redis internals as an exercise in systems programming. The focus is on understanding and rebuilding the primitives that make Redis fast:\n\n- Non-blocking TCP networking with Asio\n- RESP2 wire protocol - parsing and serialization\n- In-memory storage with TTL and lazy expiry\n- Lock-free concurrency via a dual Asio context (multi-reactor) design\n- Extensible command dispatch using the Command pattern\n- Client transactions and optimistic locking\n\n---\n\n## Current Status\n\n### Implemented\n\n#### Networking \u0026 Protocol\n- RESP2 parsing: `SimpleString`, `BulkString`, `Integer`, `Array`, `Null`\n- Multi-reactor architecture: 4 async I/O threads + 1 lock-free store thread\n- Configurable port via `--port` flag or `REDIS_PORT` environment variable\n\n#### Core Commands\n- `SET`, `GET`, `TYPE`, `INCR`\n- Key expiration via `EX` (seconds) and `PX` (milliseconds)\n- Lazy deletion of expired keys on access\n\n#### List Commands\n- `RPUSH`, `LPUSH`, `LRANGE`, `LLEN`, `LPOP`\n- `BLPOP` with configurable timeout\n\n#### Stream Commands\n- `XADD` with support for auto-generated IDs (`*`, `ms-*`)\n- `XRANGE`with support for infinite bounds (`-`, `+`)\n- `XREAD` including `BLOCK` mode and `$` for new entries only\n\n#### Transactions \u0026 Locking\n- `MULTI`, `EXEC`, `DISCARD`\n- `WATCH`, `UNWATCH`, optimistic locking with dirty-transaction detection\n\n### Planned\n\n- RDB / AOF persistence\n- Primary–replica replication\n- Pub/Sub channels and patterns\n- Sorted Sets\n- Geospatial commands\n- AUTH / ACL\n\n---\n\n## Tech Stack\n- **Language:** C++23\n- **Build System:** CMake\n- **Package Management:** vcpkg\n- **Async Networking:** Asio (standalone)\n- **Testing:** Google Test\n- **CI:** GitHub Actions\n- **Coverage:** Codecov\n\n---\n\n## Quick Start\n\n**Build and run:**\n```bash\n./program.sh\n./program.sh --port 6380\n```\n\n**Connect with any Redis client:**\n```bash\nredis-cli ping\nredis-cli -p 6379\n```\n\n**Run the test suite:**\n```bash\n./run_tests.sh\n```\n\n---\n\n## Architecture\n\nThe server separates **network I/O** from **store execution** using two independent Asio contexts. All store operations run sequentially on a single dedicated thread – no locks required.\n\n### System Overview\n\nCommands travel from the network pool to the store thread via `asio::post`, and replies return the same way.\n\n```mermaid\nflowchart LR\n    subgraph net_pool[\"Network Pool: 4 Async I/O Threads\"]\n        A[TCP Acceptor] --\u003e B[Connection]\n        B --\u003e C[RespParser]\n    end\n\n    subgraph store_thread[\"1 Store Thread: Lock-Free\"]\n        D[CommandHandler] --\u003e E[(Store)]\n        D --\u003e F[BlockingManager]\n        E --\u003e G[StringStore]\n        E --\u003e H[ListStore]\n        E --\u003e I[StreamStore]\n    end\n\n    C --\u003e|\"asio::post(store_ctx_)\"| D\n    D --\u003e|\"asio::post(socket_executor)\"| B\n```\n\n### Command Dispatch\n\n`CommandHandler` routes each request through the `TransactionDispatcher`, which either queues it inside an active `MULTI` block or resolves it immediately via `CommandRegistry`. All concrete commands implement `ICommand`.\n\n```mermaid\nclassDiagram\n    namespace Dispatch {\n        class CommandHandler {\n            -registry_ CommandRegistry\n            -dispatcher_ TransactionDispatcher\n            -tm_ TransactionManager\n            +handle(request, executor, on_reply)\n        }\n        class TransactionDispatcher {\n            +dispatch(request, cmd, executor, on_reply)\n        }\n        class TransactionManager {\n            +begin()\n            +queue_command(request)\n            +is_active() bool\n        }\n        class CommandRegistry {\n            +register_command(type, cmd)\n            +find(type) ICommand ptr\n        }\n        class ICommand {\n            \u003c\u003cinterface\u003e\u003e\n            +execute(cmd, executor, on_reply)*\n        }\n    }\n\n    CommandHandler \"1\" *-- \"1\" CommandRegistry\n    CommandHandler \"1\" *-- \"1\" TransactionDispatcher\n    CommandHandler \"1\" *-- \"1\" TransactionManager\n    TransactionDispatcher --\u003e CommandRegistry : looks up\n    TransactionDispatcher --\u003e TransactionManager : queues in\n    CommandRegistry \"1\" *-- \"*\" ICommand\n    ICommand \u003c|.. SetCommand : implements\n    ICommand \u003c|.. BlpopCommand : implements\n```\n\n---\n\n## Project Structure\n\n```\nsrc/\n├── main.cpp\n├── net/\n│   ├── Server.hpp / .cpp             # TCP acceptor, owns shared state\n│   └── Connection.hpp / .cpp         # Per-client async read loop\n├── resp/\n│   ├── RespValue.hpp                 # RESP2 value type (variant)\n│   └── RespParser.hpp / .cpp         # Stateless RESP2 parser\n├── state/\n│   ├── WatchManager.hpp / .cpp       # Shared WATCH registry for all connections\n│   └── BlockingManager.hpp / .cpp    # Shared blocking registry for BLPOP / XREAD BLOCK\n├── command/\n│   ├── core/                          # Abstractions, registry, type definitions\n│   │   ├── ICommand.hpp               # Pure-virtual command interface\n│   │   ├── Command.hpp                # Command type enum + parsing\n│   │   └── CommandRegistry.hpp / .cpp # Maps Command::Type → ICommand\n│   ├── execution/                     # Per-connection execution engine\n│   │   ├── CommandHandler.hpp / .cpp  # Routes requests via registry \u0026 dispatcher\n│   │   ├── TransactionManager.hpp / .cpp\n│   │   └── TransactionDispatcher.hpp / .cpp # MULTI/EXEC execution\n│   └── impl/                          # Concrete command implementations\n│       ├── BasicCommands.hpp / .cpp   # PING, ECHO, SET, GET, TYPE, INCR\n│       ├── ListCommands.hpp / .cpp    # RPUSH, LPUSH, LRANGE, LLEN, LPOP, BLPOP\n│       ├── StreamCommands.hpp / .cpp  # XADD, XRANGE, XREAD\n│       ├── TransactionCommands.hpp / .cpp # MULTI, EXEC, DISCARD\n│       └── WatchCommands.hpp / .cpp   # WATCH, UNWATCH\n├── store/\n│   ├── Store.hpp                      # Facade delegating to sub-stores\n│   ├── StoreValue.hpp                 # Value wrapper: std::variant\u003cstring, deque, Stream\u003e + TTL\n│   ├── impl/                          # Store implementations (per data type)\n│   │   ├── StringStore.hpp / .cpp     # String operations\n│   │   ├── ListStore.hpp / .cpp       # List operations\n│   │   └── StreamStore.hpp / .cpp     # Stream operations\n│   └── types/                         # Domain-specific data types\n│       ├── Stream.hpp                 # Stream, StreamId, StreamRange, StreamEntry\n│       └── StreamIdUtils.hpp / .cpp   # Stream ID parsing and generation\n└── util/\n    ├── Logger.hpp\n    ├── StringUtils.hpp\n    └── CommandUtils.hpp\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffgulde%2Fredis-clone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffgulde%2Fredis-clone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffgulde%2Fredis-clone/lists"}