# 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
   # Unit tests only
   cargo test --lib

   # All tests including integration (requires Docker)
   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

| Feature | Description |
|---------|-------------|
| `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.
