diff --git a/CLAUDE.md b/CLAUDE.md index 2770760..2f344bc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,10 +10,16 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co go build -o kvs . # Run with default config (auto-generates config.yaml) -./kvs +./kvs start config.yaml # Run with custom config -./kvs /path/to/config.yaml +./kvs start /path/to/config.yaml + +# Check running instances +./kvs status + +# Stop instance +./kvs stop config # Run comprehensive integration tests ./integration_test.sh @@ -25,6 +31,32 @@ go run test_conflict.go data1 data2 go build -o kvs . && ./integration_test.sh ``` +### Process Management Commands +```bash +# Start as background daemon +./kvs start # .yaml extension optional + +# Stop daemon +./kvs stop # Graceful SIGTERM shutdown + +# Restart daemon +./kvs restart # Stop then start + +# Show status +./kvs status # All instances +./kvs status # Specific instance + +# Run in foreground (for debugging) +./kvs # Logs to stdout, blocks terminal + +# View daemon logs +tail -f ~/.kvs/logs/kvs_.yaml.log + +# Global state directories +~/.kvs/pids/ # PID files (works from any directory) +~/.kvs/logs/ # Daemon log files +``` + ### Development Workflow ```bash # Format and check code @@ -38,11 +70,25 @@ go mod tidy go build . # Test specific cluster scenarios -./kvs node1.yaml & # Terminal 1 -./kvs node2.yaml & # Terminal 2 +./kvs start node1.yaml +./kvs start node2.yaml + +# Wait for cluster formation +sleep 5 + +# Test data operations curl -X PUT http://localhost:8081/kv/test/data -H "Content-Type: application/json" -d '{"test":"data"}' curl http://localhost:8082/kv/test/data # Should replicate within ~30 seconds -pkill kvs + +# Check daemon status +./kvs status + +# View logs +tail -f ~/.kvs/logs/kvs_node1.yaml.log + +# Cleanup +./kvs stop node1 +./kvs stop node2 ``` ## Architecture Overview @@ -58,7 +104,8 @@ KVS is a **distributed, eventually consistent key-value store** built around thr #### Modular Package Design - **`auth/`** - Complete JWT authentication system with POSIX-inspired permissions -- **`cluster/`** - Distributed systems logic (gossip, sync, merkle trees) +- **`cluster/`** - Distributed systems logic (gossip, sync, merkle trees) +- **`daemon/`** - Process management (daemonization, PID files, lifecycle) - **`storage/`** - BadgerDB abstraction with compression and revision history - **`server/`** - HTTP handlers, routing, and lifecycle management - **`features/`** - Utility functions for TTL, rate limiting, tamper logging, backup @@ -147,9 +194,18 @@ Creates two BadgerDB instances with intentionally conflicting data (same path, s - **Bootstrap sync**: Up to 30 days of historical data for new nodes #### Main Entry Point Flow -1. `main.go` loads config (auto-generates default if missing) -2. `server.NewServer()` initializes all subsystems -3. Graceful shutdown handling with `SIGINT`/`SIGTERM` -4. All business logic delegated to modular packages +1. `main.go` parses command-line arguments for subcommands (`start`, `stop`, `status`, `restart`) +2. For daemon mode: `daemon.Daemonize()` spawns background process and manages PID files +3. For server mode: loads config (auto-generates default if missing) +4. `server.NewServer()` initializes all subsystems +5. Graceful shutdown handling with `SIGINT`/`SIGTERM` +6. All business logic delegated to modular packages + +#### Daemon Architecture +- **PID Management**: Global PID files stored in `~/.kvs/pids/` for cross-directory access +- **Logging**: Daemon logs written to `~/.kvs/logs/{config-name}.log` +- **Process Lifecycle**: Spawns detached process via `exec.Command()` with `Setsid: true` +- **Config Normalization**: Supports both `node1` and `node1.yaml` formats +- **Stale PID Detection**: Checks process existence via `Signal(0)` before operations This architecture enables easy feature addition, comprehensive testing, and reliable operation in distributed environments while maintaining simplicity for single-node deployments. \ No newline at end of file diff --git a/README.md b/README.md index d58f4dd..d9a0f43 100644 --- a/README.md +++ b/README.md @@ -69,11 +69,67 @@ go build -o kvs . ### Quick Test ```bash -# Start standalone node -./kvs +# Start standalone node (uses config.yaml if it exists, or creates it) +./kvs start config.yaml # Test the API curl http://localhost:8080/health + +# Check status +./kvs status + +# Stop when done +./kvs stop config +``` + +## 🎮 Process Management + +KVS includes systemd-style daemon commands for easy process management: + +```bash +# Start as background daemon +./kvs start config.yaml # or just: ./kvs start config +./kvs start node1.yaml # Start with custom config + +# Check status +./kvs status # Show all running instances +./kvs status node1 # Show specific instance + +# Stop daemon +./kvs stop node1 # Graceful shutdown + +# Restart daemon +./kvs restart node1 # Stop and start + +# Run in foreground (traditional) +./kvs node1.yaml # Logs to stdout +``` + +### Daemon Features +- **Global PID tracking**: PID files stored in `~/.kvs/pids/` (works from any directory) +- **Automatic logging**: Logs written to `~/.kvs/logs/{config-name}.log` +- **Flexible naming**: Config extension optional (`node1` or `node1.yaml` both work) +- **Graceful shutdown**: SIGTERM sent for clean shutdown +- **Stale PID cleanup**: Automatically detects and cleans dead processes +- **Multi-instance**: Run multiple KVS instances on same machine + +### Example Workflow +```bash +# Start 3-node cluster as daemons +./kvs start node1.yaml +./kvs start node2.yaml +./kvs start node3.yaml + +# Check cluster status +./kvs status + +# View logs +tail -f ~/.kvs/logs/kvs_node1.yaml.log + +# Stop entire cluster +./kvs stop node1 +./kvs stop node2 +./kvs stop node3 ``` ## ⚙️ Configuration @@ -308,17 +364,23 @@ clustering_enabled: true #### Start the Cluster ```bash -# Terminal 1 -./kvs node1.yaml - -# Terminal 2 (wait a few seconds) -./kvs node2.yaml - -# Terminal 3 (wait a few seconds) -./kvs node3.yaml +# Start as daemons +./kvs start node1.yaml +sleep 2 +./kvs start node2.yaml +sleep 2 +./kvs start node3.yaml # Verify cluster formation curl http://localhost:8081/members/ # Should show all 3 nodes + +# Check daemon status +./kvs status + +# Stop cluster when done +./kvs stop node1 +./kvs stop node2 +./kvs stop node3 ``` ## 🔄 How It Works @@ -364,9 +426,10 @@ go build -o kvs . ./integration_test.sh # Manual basic functionality test -./kvs & +./kvs start config.yaml +sleep 2 curl http://localhost:8080/health -pkill kvs +./kvs stop config # Manual cluster test (requires creating configs) echo 'node_id: "test1" @@ -379,8 +442,9 @@ port: 8082 seed_nodes: ["127.0.0.1:8081"] auth_enabled: false' > test2.yaml -./kvs test1.yaml & -./kvs test2.yaml & +./kvs start test1.yaml +sleep 2 +./kvs start test2.yaml # Test data replication (wait for cluster formation) sleep 10 @@ -393,7 +457,8 @@ sleep 30 curl http://localhost:8082/kv/test/data # Cleanup -pkill kvs +./kvs stop test1 +./kvs stop test2 rm test1.yaml test2.yaml ``` @@ -418,17 +483,22 @@ auth_enabled: false log_level: "debug"' > conflict2.yaml # Start nodes with conflicting data -./kvs conflict1.yaml & -./kvs conflict2.yaml & +./kvs start conflict1.yaml +sleep 2 +./kvs start conflict2.yaml # Watch logs for conflict resolution +tail -f ~/.kvs/logs/kvs_conflict1.yaml.log ~/.kvs/logs/kvs_conflict2.yaml.log & + # Both nodes will converge within ~10-30 seconds # Check final state sleep 30 curl http://localhost:9111/kv/test/conflict/data curl http://localhost:9112/kv/test/conflict/data -pkill kvs +# Cleanup +./kvs stop conflict1 +./kvs stop conflict2 rm conflict1.yaml conflict2.yaml ``` @@ -474,6 +544,10 @@ kvs/ ├── config/ # Configuration management │ └── config.go # Config loading & defaults │ +├── daemon/ # Process management +│ ├── daemonize.go # Background process spawning +│ └── pid.go # PID file management +│ ├── features/ # Utility features │ ├── auth.go # Auth utilities │ ├── backup.go # Backup system @@ -580,8 +654,9 @@ type StoredValue struct { ## 🛡️ Production Considerations ### Deployment -- Use systemd or similar for process management -- Configure log rotation for JSON logs +- Built-in daemon commands (`start`/`stop`/`restart`/`status`) for process management +- Alternatively, use systemd or similar for advanced orchestration +- Logs automatically written to `~/.kvs/logs/` (configure log rotation) - Set up monitoring for `/health` endpoint - Use reverse proxy (nginx/traefik) for TLS and load balancing