# Contributing to photon-etcd-cluster
Thank you for your interest in contributing to photon-etcd-cluster! This document provides guidelines and information for contributors.
## Code of Conduct
Please be respectful and constructive in all interactions. We welcome contributors of all experience levels.
## Getting Started
### Prerequisites
- Rust 1.85 or later (edition 2024)
- Docker (for integration tests)
- etcd v3.5+ (for local development)
### Setting Up Development Environment
1. Clone the repository:
```bash
git clone https://github.com/rgushel/photon-etcd-cluster.git
cd photon-etcd-cluster
```
2. Build the project:
```bash
cargo build
```
3. Build with all features:
```bash
cargo build --features system-metrics
```
4. Run tests:
```bash
cargo test --lib
cargo test -- --test-threads=1
```
## How to Contribute
### Reporting Bugs
- Check existing issues to avoid duplicates
- Use a clear, descriptive title
- Include steps to reproduce the issue
- Provide your Rust version and OS
- Include relevant logs or error messages
### Suggesting Features
- Open an issue with the `enhancement` label
- Describe the use case and expected behavior
- Explain why this would be useful to other users
### Pull Requests
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/your-feature`
3. Make your changes
4. Run tests and ensure they pass
5. Run `cargo fmt` and `cargo clippy --all-features`
6. Ensure documentation builds without warnings: `cargo doc --no-deps`
7. Commit with a clear message
8. Push and create a Pull Request
### Commit Messages
Follow conventional commit format:
```
type(scope): description
[optional body]
[optional footer]
```
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
Examples:
- `feat(cluster_node): add graceful shutdown with CancellationToken`
- `fix(discovery): handle etcd reconnection on network partition`
- `docs: update README with TLS configuration`
## Code Style
### Rust Guidelines
- Follow standard Rust formatting (`cargo fmt`)
- Address all clippy warnings (`cargo clippy --all-features`)
- Use `thiserror` for error types
- Use `tracing` for logging (not `println!` or `log`)
- Avoid `.unwrap()` - propagate errors with `?` or handle explicitly
- Prefer `Arc<AtomicBool>` over `Arc<Mutex<bool>>` for simple flags
- Use `tokio::sync::watch` for shared state that changes infrequently
### Documentation
- Add doc comments to public APIs
- Include examples in doc comments where helpful
- Update README.md for user-facing changes
- Update CLAUDE.md for architecture/development changes
### Testing
- Write unit tests for new functionality
- Add integration tests for etcd interactions
- Ensure tests are deterministic and don't depend on timing
- Use `#[serial_test::serial]` for tests that share resources
- Integration tests require Docker (spawns etcd on port 2377)
## Architecture Overview
```
src/
├── lib.rs # Public module exports and re-exports
├── cluster_node/
│ ├── mod.rs # ClusterNode + ClusterNodeBuilder
│ ├── election.rs # Leader election logic
│ ├── lease.rs # etcd lease management
│ ├── metrics_task.rs # Background metrics update task
│ └── state.rs # Node state management
├── discovery/
│ ├── mod.rs # ServiceDiscovery
│ ├── handlers.rs # Event handlers
│ ├── state.rs # Cluster state management
│ └── watch_loop.rs # etcd watch loop
├── connection.rs # etcd connection with retry logic
├── error.rs # ClusterError type
├── event.rs # ClusterEvent enum
├── metrics.rs # MetricsCollector trait + implementations
└── types.rs # Node, HealthStatus, NodeMetadata
```
### Key Design Decisions
- **Lock-free reads**: `ServiceDiscovery.nodes()` uses `watch::Receiver::borrow()` for O(1) access
- **Graceful shutdown**: All loops accept `broadcast::Receiver<()>` for termination
- **Resilient connectivity**: Exponential backoff on etcd failures (1s → 30s max)
- **Reactive API**: Event-driven with broadcast channels and watch streams
### etcd Key Structure
```
registry/{group_name}/{node_id} → Node JSON
election/{group_name} → leader election key
```
## Features
| `default` | Core functionality without system metrics |
| `system-metrics` | Enables `SystemMetricsCollector` for CPU, memory, load metrics (adds `sysinfo` dependency) |
## Release Process
1. Update version in `Cargo.toml`
2. Update CHANGELOG.md with new version section
3. Run full test suite: `cargo test -- --test-threads=1`
4. Verify package: `cargo publish --dry-run`
5. Commit changes: `git commit -am "chore: release vX.Y.Z"`
6. Create a git tag: `git tag vX.Y.Z`
7. Push with tags: `git push origin master --tags`
8. Publish to crates.io: `cargo publish`
## Questions?
Open an issue or reach out to the maintainers. We're happy to help!
## License
By contributing to photon-etcd-cluster, you agree that your contributions will be licensed under the MIT License.