First off, thank you for considering contributing to ApexStore! 🎉
This document provides guidelines and instructions for contributing to the project. Following these guidelines helps maintain code quality and makes the review process smoother.
- Code of Conduct
- Getting Started
- Development Workflow
- Coding Standards
- Testing Guidelines
- Commit Messages
- Pull Request Process
- Project Structure
- Areas for Contribution
We are committed to providing a welcoming and inspiring community for all. We pledge to:
- Be respectful and inclusive
- Accept constructive criticism gracefully
- Focus on what is best for the community
- Show empathy towards other community members
- Use welcoming and inclusive language
- Be respectful of differing viewpoints and experiences
- Gracefully accept constructive criticism
- Focus on what is best for the community
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information without explicit permission
- Other conduct which could reasonably be considered inappropriate
-
Rust Toolchain (1.70 or later)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
Git
# Ubuntu/Debian sudo apt-get install git # macOS brew install git
-
Code Editor (Recommended: VS Code with rust-analyzer)
- Install VS Code
- Install rust-analyzer extension
-
Fork the Repository
- Visit https://github.com/ElioNeto/ApexStore
- Click the "Fork" button in the top-right corner
-
Clone Your Fork
git clone https://github.com/YOUR_USERNAME/ApexStore.git cd ApexStore -
Add Upstream Remote
git remote add upstream https://github.com/ElioNeto/ApexStore.git
-
Install Dependencies
cargo build
-
Run Tests
cargo test
For detailed setup instructions, see SETUP.md.
ApexStore uses GitHub Actions to automate the development workflow:
- Feature/Fix branches → Auto-create PR to
develop+ run tests - Develop → Auto-create release PR to
main - Main → Create release tag + close related issues
See WORKFLOWS.md for complete documentation.
# Update your fork
git checkout main
git pull upstream main
# Create a new branch from main
git checkout -b feature/your-feature-nameBranch Naming Conventions:
feature/- New features (e.g.,feature/compaction-strategy)fix/- Bug fixes (e.g.,fix/wal-corruption)docs/- Documentation changes (e.g.,docs/api-guide)refactor/- Code refactoring (e.g.,refactor/codec-interface)test/- Test additions/improvements (e.g.,test/integration-suite)perf/- Performance improvements (e.g.,perf/bloom-filter-optimization)
# Make changes to the code
vim src/core/engine.rs
# Test your changes
cargo test --all-features
# Format code
cargo fmt
# Check for issues
cargo clippy --all-features -- -D warningsgit add .
git commit -m "feat: add compaction strategy interface (#55)"Important: Reference issues in commit messages using #issue_number for automatic tracking.
See Commit Messages for formatting guidelines.
git push origin feature/your-feature-nameWhat Happens Next:
- ✅ GitHub Actions automatically runs tests
- ✅ Auto-creates PR to
developbranch - ✅ Adds comment to referenced issues (if any)
- ✅ Runs Clippy and format checks
Once the automated PR is created:
- Review the PR description
- Wait for CI checks to pass
- Address any reviewer feedback
- PR will be merged to
developonce approved
Note: You don't need to manually create PRs - the workflow handles this automatically!
We follow the Rust API Guidelines and Rust Style Guide.
Key Principles:
-
Use
cargo fmt- All code must be formattedcargo fmt --all
-
Pass
cargo clippy- Zero warnings policycargo clippy --all-features -- -D warnings
-
Write Documentation - Public APIs must have doc comments
/// Retrieves a value from the store by key. /// /// # Arguments /// /// * `key` - The key to look up /// /// # Returns /// /// * `Ok(Some(value))` - Key found /// * `Ok(None)` - Key not found /// * `Err(e)` - Error occurred /// /// # Example /// /// ``` /// let value = engine.get(b"user:123")?; /// ``` pub fn get(&self, key: &[u8]) -> Result<Option<String>> { // Implementation }
This project follows SOLID principles:
- Single Responsibility: Each module/struct has one clear purpose
- Open/Closed: Extend behavior through traits, not modification
- Liskov Substitution: Implementations must be interchangeable
- Interface Segregation: Small, focused traits
- Dependency Inversion: Depend on abstractions, not concretions
Example:
// ✅ Good - depends on trait
pub struct LsmEngine<W: WriteAheadLog> {
wal: W,
}
// ❌ Bad - depends on concrete type
pub struct LsmEngine {
wal: FileBasedWal,
}-
Use
Result<T, LsmError>for fallible operationspub fn put(&mut self, key: &[u8], value: &str) -> Result<()> { self.wal.append(key, value)?; self.memtable.insert(key, value); Ok(()) }
-
Provide Context with error types
use thiserror::Error; #[derive(Error, Debug)] pub enum LsmError { #[error("WAL corruption at offset {0}")] WalCorruption(u64), #[error("Key too large: {size} bytes (max: {max})")] KeyTooLarge { size: usize, max: usize }, }
-
Don't Panic in library code (use
Resultinstead)
-
Minimize Allocations
// ✅ Good - reuse buffer let mut buffer = Vec::with_capacity(1024); for item in items { buffer.clear(); serialize_into(&mut buffer, item)?; } // ❌ Bad - allocate each iteration for item in items { let buffer = serialize(item)?; }
-
Use Appropriate Data Structures
BTreeMapfor sorted dataHashMapfor fast lookupsVecfor sequential access
-
Benchmark Changes
cargo bench
-
Unit Tests - Test individual functions/modules
#[cfg(test)] mod tests { use super::*; #[test] fn test_memtable_insert() { let mut memtable = MemTable::new(); memtable.insert(b"key", "value"); assert_eq!(memtable.get(b"key"), Some("value".to_string())); } }
-
Integration Tests - Test component interactions
// tests/integration_test.rs #[test] fn test_engine_recovery() { let config = LsmConfig::default(); let mut engine = LsmEngine::new(config).unwrap(); engine.put(b"key", "value").unwrap(); drop(engine); let engine = LsmEngine::new(config).unwrap(); assert_eq!(engine.get(b"key").unwrap(), Some("value".to_string())); }
-
Property Tests - Test invariants (optional, using
proptest)
- All new code must have tests
- Tests must pass on all platforms
- Test coverage should increase, not decrease
- Use descriptive test names
#[test] fn test_get_returns_none_for_nonexistent_key() { /* ... */ }
# Run all tests
cargo test --all-features
# Run specific test
cargo test test_memtable_insert
# Run with output
cargo test -- --nocapture
# Run integration tests only
cargo test --test '*'
# Run with coverage (requires tarpaulin)
cargo tarpaulin --out HtmlWe follow the Conventional Commits specification.
<type>(<scope>): <subject> (#issue)
<body>
<footer>
feat- New featurefix- Bug fixdocs- Documentation changesstyle- Code style changes (formatting, etc.)refactor- Code refactoringperf- Performance improvementstest- Test additions/modificationschore- Build process, dependencies, toolingci- CI/CD changes
Simple commit:
feat: add bloom filter to SSTable reader
With scope and issue:
fix(wal): prevent corruption on unclean shutdown (#42)
With body:
feat(compaction): implement leveled compaction strategy (#47)
Adds a new LeveledCompaction struct that implements the Compaction
trait. This strategy reduces read amplification by maintaining
sorted levels with exponentially increasing sizes.
Closes #47
Breaking change:
feat(api)!: change SSTable format to V2
BREAKING CHANGE: SSTable V2 is incompatible with V1.
Migration tool will be provided in v1.4.
Referencing Issues:
#123- Reference issuefixes #123,closes #123- Will auto-close issue when PR mergesresolves #123- Alternative close syntax
- Code compiles without errors
- All tests pass (
cargo test --all-features) - No clippy warnings (
cargo clippy --all-features -- -D warnings) - Code is formatted (
cargo fmt) - Documentation is updated (if applicable)
- Tests are added for new functionality
When you push to a feature/* or fix/* branch:
- ✅ Tests run automatically (CI/CD)
- ✅ PR is auto-created to
developbranch - ✅ Issues are commented (if referenced in commits)
- ✅ Checks must pass before merge
If you need to create a PR manually:
- Go to your fork on GitHub
- Click "New Pull Request"
- Select
developas the base branch - Fill out the PR template
- Submit the PR
When creating a PR manually, use this template:
## Description
Brief description of changes.
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Related Issues
Closes #123
Related to #456
## Testing
Describe how you tested your changes:
- [ ] Unit tests added
- [ ] Integration tests added
- [ ] Manual testing performed
## Checklist
- [ ] Code compiles
- [ ] Tests pass
- [ ] Clippy checks pass
- [ ] Code is formatted
- [ ] Documentation updated
## Screenshots (if applicable)
## Additional Notes- Automated Checks - CI runs tests and linters
- Code Review - Maintainer reviews code
- Feedback - Address review comments
- Approval - Maintainer approves PR
- Merge - Squash and merge to
develop
- Simple PRs: 1-3 days
- Complex PRs: 3-7 days
- Breaking Changes: 7-14 days
ApexStore/
├── src/
│ ├── core/ # Core domain logic
│ │ ├── engine.rs # LSM engine orchestration
│ │ ├── memtable.rs # In-memory storage
│ │ └── log_record.rs # Data model
│ ├── storage/ # Persistence layer
│ │ ├── wal.rs # Write-ahead log
│ │ ├── sstable.rs # SSTable reader
│ │ └── builder.rs # SSTable writer
│ ├── infra/ # Infrastructure
│ │ ├── codec.rs # Serialization
│ │ ├── error.rs # Error types
│ │ └── config.rs # Configuration
│ ├── api/ # HTTP API (feature-gated)
│ ├── cli/ # CLI interface
│ └── features/ # Feature flags
├── tests/ # Integration tests
├── benches/ # Benchmarks
└── docs/ # Documentation
core/- Domain logic, no external dependenciesstorage/- File I/O, persistenceinfra/- Cross-cutting concernsapi/- External interfaces (feature-gated)
-
CI/CD Testing Pipeline (#55)
- Difficulty: Easy
- Impact: High
- Skills: GitHub Actions, YAML
-
Compaction Implementation (#47)
- Difficulty: Hard
- Impact: High
- Skills: Rust, algorithms, file I/O
-
Efficient Iterators (#21, #22, #23)
- Difficulty: Medium
- Impact: High
- Skills: Rust, data structures
-
Benchmarking Suite (#48)
- Difficulty: Easy
- Impact: Medium
- Skills: Rust, criterion
-
CLI Command Equalization (#65)
- Difficulty: Medium
- Impact: Medium
- Skills: Rust, CLI design
-
Checksums & Integrity (#25)
- Difficulty: Easy
- Impact: High
- Skills: Rust, CRC32
-
Add More Tests
- Difficulty: Easy
- Impact: Medium
- Skills: Rust, testing
-
Binary Search Optimization (#37)
- Difficulty: Easy
- Impact: Medium
- Skills: Rust, algorithms
-
Documentation Improvements
- Difficulty: Easy
- Impact: Medium
- Skills: Technical writing
-
Replication Support
- Difficulty: Very Hard
- Impact: Very High
- Skills: Distributed systems, Raft
-
Snapshot Isolation
- Difficulty: Hard
- Impact: High
- Skills: Concurrency, MVCC
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: docs/
- Email: netoo.elio@hotmail.com
- Find an issue or create one
- Comment that you're working on it
- Fork the repo and create a branch from
main - Make your changes with tests
- Push to your fork (automated PR will be created)
- Wait for review and address feedback
Thank you for contributing! 🎉
Last updated: March 2026