First off — thank you for taking the time to contribute! 🦀
FerrumKV is a from-scratch RESP2-compatible KV storage server built for systems programming practice. Whether you are fixing a typo, reporting a bug, or implementing a new command, your contribution is welcome.
This document is the single source of truth for how to participate. Please read it before opening your first issue or pull request.
TL;DR — fork → branch →
cargo fmt && cargo clippy && cargo test→ open a PR againstmasterwith a Conventional Commit title. The rest of this file explains each step.
By participating you agree to uphold the standards in
CODE_OF_CONDUCT.md. Please report unacceptable
behaviour to the maintainers listed at the bottom of that file.
src/
cli.rs # argument parsing + engine wiring
main.rs # entry point, signal handlers
config/ # Redis-style config file parser
error/ # unified FerrumError (9 variants)
network/ # TCP accept loop, shutdown, command dispatch
persistence/ # AOF writer + replay
protocol/ # RESP2 parser + encoder
storage/ # KvEngine, eviction, expire
tests/ # 9 integration suites (real TCP listener)
benches/ # Criterion microbenchmarks
.issues/ # local issue tracker (see .issues/README.md)
.github/ # CI workflow + issue/PR templates
docs/ # development plan + whitepaper
A fuller architectural reference lives in .atomcode.md and the
top-level README.
- Check existing issues. Look in the GitHub issue tracker
and the local
.issues/directory — someone may already be working on it, or the behaviour may be a documented intentional deviation from Redis (tracked asFERRUM-NNN). - Open an issue first for non-trivial work. New commands, behaviour changes, or refactors larger than ~50 lines should be discussed in an issue before you write code, so we can agree on scope and avoid wasted effort.
- Pick a branch name following the Conventional Commits type:
feat/<slug>,fix/<slug>,refactor/<slug>,test/<slug>,docs/<slug>,bench/<slug>,ci/<slug>,chore/<slug>.
gh repo fork phaethix/ferrum-kv --clone
cd ferrum-kvgit checkout master
git pull
git checkout -b feat/<your-slug>FerrumKV follows test-driven development for new features and bug fixes. Write a failing test that captures the desired behaviour, then make it pass.
cargo test # unit + integration
cargo test --test resp2_wire_test # one suite
cargo test binary_safe # filtered testsWire-protocol behaviour should be verified end-to-end in
tests/resp2_wire_test.rs against a real TCP listener rather than with
mocks — prefer adding cases there.
cargo fmt --all # auto-format
cargo fmt --all -- --check # verify no diff
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets --all-features
cargo bench --no-run --all-features # benches must compileCI runs these exact commands on every push and pull request. A PR that
fails any gate will not be merged. The project enforces -D warnings,
so even a stray unused_import blocks the build.
Each commit message must start with one of:
| Type | Use for |
|---|---|
feat: |
A new command, capability, or user-facing behaviour |
fix: |
A bug fix |
refactor: |
Code restructuring with no behaviour change |
test: |
Adding or improving tests |
docs: |
Documentation only |
bench: |
Benchmark additions or changes |
ci: |
CI/build pipeline changes |
chore: |
Releases, version bumps, dependency updates |
Optional scope: feat(network): .... The title line stays ≤ 72 chars,
imperative mood (add, not added/adds). Reference issues in the body
as FERRUM-NNN:
feat(expire): add EXPIAT support
Implements EXPIAT as a unix-seconds variant of PEXPIREAT, mirroring
Redis semantics. Closes FERRUM-006.
Co-Authored-By: Jane Doe <jane@example.com>
Keep commits focused and atomic — one logical change per commit. Use
git rebase -i master to tidy history before pushing.
git push -u origin feat/<your-slug>Open the PR against master. Fill in the pull request template
(.github/PULL_REQUEST_TEMPLATE.md) — it asks for a summary, the
motivation, the test plan, and a checklist of the quality gates.
These are project-specific invariants. Violating them will block a PR regardless of whether CI is green.
Keys and values are Vec<u8>. Never assume UTF-8 in the data path
or introduce String/str conversions there. NUL, \r\n, and
non-UTF-8 sequences must round-trip through the network layer and the
AOF unchanged. The binary_safe_* and non_utf8_* tests guard this —
keep them passing.
FerrumKV speaks RESP2 only. Inline commands are rejected (the first byte
must be *). Redis is the reference semantics: when you add or change a
command, check Redis behaviour first. Any intentional deviation must be
documented in the README and have a test asserting the chosen behaviour,
and be tracked in .issues/.
Any code path that removes a key (del_many, sweep_expired,
enforce_memory_limit, overwrite via set) must call track_remove
and aof.append_del (if AOF is enabled). This is the cross-cutting
invariant — see enforce_memory_limit and sweep_expired for the
canonical pattern.
- All fallible operations return
Result<_, FerrumError>. - Never
.unwrap()on runtime data..unwrap()is only acceptable where a prior arity/guard check guarantees safety (the existing pattern inbuild_command). - Panics in the data path are bugs. Lock poisoning propagates via
From<PoisonError>— use?, don't catch. FerrumError::Displaytext is the client-facing-ERRmessage — write it for operators, not for debugging.
No unsafe unless justified in a // SAFETY: comment. The project
currently has none.
- 4-space indent;
cargo fmtis authoritative — do not hand-format. - Public items have
///doc comments; private helpers may use//. - Match arms favour exhaustiveness over a
_ =>catch-all wherever the enum is owned by this crate, so new variants force compiler-driven updates. - Match the surrounding file's comment density — do not over-comment obvious code, and preserve existing (including Chinese) comments.
Open a GitHub issue using the Bug report template. A good bug report includes:
- FerrumKV version (
ferrum-kv --versionor the git commit). - The exact command used to start the server (flags matter — AOF,
--io-threads,--appendfsync). - A minimal reproduction with
redis-clicommands. Prefer real client input over hand-crafted RESP frames. - Expected vs actual output, with Redis behaviour as the reference baseline where applicable.
- Logs / backtrace if the server crashed.
Security-sensitive bugs must not be filed as public issues — see
SECURITY.md for responsible disclosure.
Open a GitHub issue using the Feature request template. Describe the use case and why the existing commands do not cover it. If you can, sketch the RESP2 response shape and the closest Redis analogue. Be prepared to discuss scope before implementation begins.
Findings discovered during code review are recorded in .issues/ as
numbered FERRUM-NNN records (see .issues/README.md
for the format). When a finding is promoted to a GitHub issue, the local
file becomes the detailed record and the GitHub issue holds the
discussion. Reference FERRUM-NNN in commit and PR bodies.
By contributing you agree that your changes will be licensed under the project's MIT license. No further CLA is required.
| Handle | Role |
|---|---|
| @phaethix | Lead maintainer |
Need help? Open an issue and mention @phaethix.