Implement readiness endpoint (/api/ready) that returns:
- {"ready":true} (HTTP 200) during normal operation
- {"ready":false} (HTTP 503) during graceful shutdown
Key changes:
- Added readiness context to control readiness state
- Modified server.NewServer() to accept readiness context
- Implemented handleReadiness() with context-aware logic
- Updated cmd/server/main.go to manage readiness state
- Readiness set to false when shutdown signal received
- Updated test script to validate readiness behavior
- Added comprehensive documentation for readiness endpoint
This allows Kubernetes/service meshes to stop routing traffic
to the pod during graceful shutdown while allowing existing
requests to complete. Health endpoint continues to return
happy status during shutdown for proper orchestration.
704 lines
16 KiB
Markdown
704 lines
16 KiB
Markdown
# DanceLessonsCoach - AI Agent Documentation
|
|
|
|
This file documents the AI agents, tools, and development workflow for the DanceLessonsCoach project.
|
|
|
|
## 🎯 Project Overview
|
|
|
|
**DanceLessonsCoach** is a Go-based web service with CLI capabilities, featuring:
|
|
- RESTful JSON API with Chi router
|
|
- High-performance Zerolog logging
|
|
- Interface-based architecture
|
|
- Context-aware services
|
|
- Comprehensive testing
|
|
|
|
## 📋 Development Timeline
|
|
|
|
### Phase 1: Foundation (Completed ✅)
|
|
- Go 1.26.1 environment setup
|
|
- Project structure with `cmd/` and `pkg/` directories
|
|
- Core Greet service implementation
|
|
- CLI interface
|
|
- Unit tests
|
|
|
|
### Phase 2: Web API (Completed ✅)
|
|
- Chi router integration
|
|
- Versioned API endpoints (`/api/v1`)
|
|
- Health endpoint (`/api/health`)
|
|
- JSON responses with proper headers
|
|
|
|
### Phase 3: Logging & Architecture (Completed ✅)
|
|
- Zerolog integration with Trace level
|
|
- Context-aware logging
|
|
- Interface-based design patterns
|
|
- Dependency injection
|
|
|
|
### Phase 4: Documentation & Testing (Completed ✅)
|
|
- Comprehensive AGENTS.md
|
|
- README.md with usage instructions
|
|
- Server management guide
|
|
- API endpoint documentation
|
|
|
|
### Phase 5: Configuration Management (Completed ✅)
|
|
- Viper integration for configuration
|
|
- Environment variable support with DLC_ prefix
|
|
- Customizable server host/port
|
|
- Configurable shutdown timeout
|
|
- Configuration validation and logging
|
|
- Example configuration file
|
|
|
|
## 🛠️ Tools & Technologies
|
|
|
|
| Component | Technology | Version |
|
|
|-----------|------------|---------|
|
|
| Language | Go | 1.26.1 |
|
|
| Router | Chi | v5.2.5 |
|
|
| Logging | Zerolog | v1.35.0 |
|
|
| Configuration | Viper | v1.21.0 |
|
|
| Testing | Standard Library | - |
|
|
| Dependency Management | Go Modules | - |
|
|
|
|
## 🗺️ Project Structure
|
|
|
|
```
|
|
DanceLessonsCoach/
|
|
├── cmd/
|
|
│ ├── greet/ # CLI application
|
|
│ │ └── main.go
|
|
│ └── server/ # Web server
|
|
│ └── main.go
|
|
├── pkg/
|
|
│ ├── config/ # Configuration management
|
|
│ │ └── config.go # Viper-based config
|
|
│ ├── greet/ # Core domain logic
|
|
│ │ ├── api_v1.go # API handlers
|
|
│ │ ├── greet.go # Service implementation
|
|
│ │ └── greet_test.go # Unit tests
|
|
│ └── server/ # HTTP server
|
|
│ └── server.go
|
|
├── go.mod # Dependencies
|
|
├── go.sum # Dependency checksums
|
|
├── config.example.yaml # Configuration template
|
|
├── README.md # User documentation
|
|
├── AGENTS.md # This file
|
|
└── .gitignore # Ignore patterns
|
|
```
|
|
|
|
## 🚀 Server Management
|
|
|
|
### Using the Server Control Script
|
|
|
|
A convenient shell script is provided for managing the server lifecycle:
|
|
|
|
```bash
|
|
# Navigate to project directory
|
|
cd /Users/gabrielradureau/Work/Vibe/DanceLessonsCoach
|
|
|
|
# Start the server
|
|
./scripts/start-server.sh start
|
|
|
|
# Check server status
|
|
./scripts/start-server.sh status
|
|
|
|
# Test API endpoints
|
|
./scripts/start-server.sh test
|
|
|
|
# View server logs
|
|
./scripts/start-server.sh logs
|
|
|
|
# Stop the server
|
|
./scripts/start-server.sh stop
|
|
```
|
|
|
|
**Server Control Script Commands:**
|
|
- `start` - Start the server in background with proper logging
|
|
- `stop` - Stop the server gracefully
|
|
- `restart` - Restart the server
|
|
- `status` - Check if server is running
|
|
- `logs` - Show recent server logs
|
|
- `test` - Test all API endpoints
|
|
|
|
### Manual Server Management
|
|
|
|
If you prefer manual control:
|
|
|
|
```bash
|
|
# Navigate to project directory
|
|
cd /Users/gabrielradureau/Work/Vibe/DanceLessonsCoach
|
|
|
|
# Run server in background
|
|
go run cmd/server/main.go &
|
|
```
|
|
|
|
**Expected output:**
|
|
```
|
|
Server running on :8080
|
|
[INF] Starting HTTP server on :8080
|
|
[TRC] Registering greet routes
|
|
[TRC] Greet routes registered
|
|
```
|
|
|
|
**Features:**
|
|
- Context-aware server initialization
|
|
- Graceful shutdown handling
|
|
- Signal-based termination (SIGINT, SIGTERM)
|
|
- 30-second shutdown timeout
|
|
- Proper resource cleanup
|
|
|
|
### Configuration Management
|
|
|
|
The server supports flexible configuration through environment variables with the `DLC_` prefix:
|
|
|
|
**Available Configuration Options:**
|
|
|
|
| Option | Environment Variable | Default Value | Description |
|
|
|--------|---------------------|---------------|-------------|
|
|
| Host | `DLC_SERVER_HOST` | `0.0.0.0` | Server bind address |
|
|
| Port | `DLC_SERVER_PORT` | `8080` | Server listening port |
|
|
| Shutdown Timeout | `DLC_SHUTDOWN_TIMEOUT` | `30s` | Graceful shutdown timeout |
|
|
| JSON Logging | `DLC_LOGGING_JSON` | `false` | Enable JSON format logging |
|
|
|
|
**Usage Examples:**
|
|
|
|
```bash
|
|
# Custom port
|
|
export DLC_SERVER_PORT=9090
|
|
go run cmd/server/main.go &
|
|
|
|
# Custom host and port
|
|
export DLC_SERVER_HOST="127.0.0.1"
|
|
export DLC_SERVER_PORT=8081
|
|
go run cmd/server/main.go &
|
|
|
|
# Custom shutdown timeout
|
|
export DLC_SHUTDOWN_TIMEOUT=45s
|
|
go run cmd/server/main.go &
|
|
|
|
# Enable JSON logging
|
|
export DLC_LOGGING_JSON=true
|
|
go run cmd/server/main.go &
|
|
```
|
|
|
|
**Configuration File Support:**
|
|
|
|
A `config.example.yaml` file is provided as a template. By default, the application looks for `config.yaml` in the current working directory.
|
|
|
|
To specify a custom config file path, set the `DLC_CONFIG_FILE` environment variable:
|
|
|
|
```bash
|
|
DLC_CONFIG_FILE="/path/to/config.yaml" go run ./cmd/server
|
|
```
|
|
|
|
Example `config.yaml`:
|
|
|
|
```yaml
|
|
server:
|
|
host: "0.0.0.0"
|
|
port: 8080
|
|
|
|
shutdown:
|
|
timeout: 30s
|
|
|
|
logging:
|
|
json: false
|
|
```
|
|
|
|
**Configuration Loading:**
|
|
- **File-based configuration** takes highest precedence
|
|
- **Environment variables** override defaults but are overridden by config file
|
|
- **Default values** are used when no other configuration is provided
|
|
- All configuration is validated on startup
|
|
- Invalid configurations cause server startup failure
|
|
- Configuration values and source are logged at startup
|
|
|
|
**Verification:**
|
|
```bash
|
|
# Test with custom configuration
|
|
DLC_SERVER_PORT=9090 DLC_SERVER_HOST="127.0.0.1" go run cmd/server/main.go
|
|
|
|
# Verify it's running on the custom port
|
|
curl http://127.0.0.1:9090/api/health
|
|
# Expected: {"status":"healthy"}
|
|
```
|
|
|
|
### Checking Server Status
|
|
|
|
```bash
|
|
# Check health endpoint
|
|
curl -s http://localhost:8080/api/health
|
|
|
|
# Check readiness endpoint
|
|
curl -s http://localhost:8080/api/ready
|
|
```
|
|
|
|
**Expected responses:**
|
|
- Health: `{"status":"healthy"}`
|
|
- Readiness (normal): `{"ready":true}`
|
|
- Readiness (during shutdown): `{"ready":false}` with HTTP 503
|
|
|
|
**Endpoint Differences:**
|
|
- **Health endpoint** (`/api/health`): Indicates if the application is running and functional
|
|
- **Readiness endpoint** (`/api/ready`): Indicates if the application is ready to accept traffic
|
|
|
|
**Use Cases:**
|
|
- **Health**: Used by load balancers to check if the app is alive
|
|
- **Readiness**: Used by Kubernetes/service meshes to determine if the app can accept new requests
|
|
|
|
**During Graceful Shutdown:**
|
|
- Health endpoint continues to return `{"status":"healthy"}`
|
|
- Readiness endpoint returns `{"ready":false}` with HTTP 503 Service Unavailable
|
|
- This allows existing requests to complete while preventing new requests
|
|
|
|
### Stopping the Server
|
|
|
|
To stop the server gracefully:
|
|
```bash
|
|
# Send SIGTERM for graceful shutdown
|
|
kill -TERM $(lsof -ti :8080)
|
|
|
|
# Or send SIGINT (Ctrl+C equivalent)
|
|
pkill -INT -f "go run"
|
|
```
|
|
|
|
**Graceful shutdown process:**
|
|
1. Server receives termination signal
|
|
2. Logs shutdown message
|
|
3. Stops accepting new connections
|
|
4. Waits up to 30 seconds for active requests to complete
|
|
5. Closes all connections cleanly
|
|
6. Exits with proper cleanup
|
|
|
|
For force stop (if graceful shutdown hangs):
|
|
```bash
|
|
kill -9 $(lsof -ti :8080)
|
|
```
|
|
|
|
**Verification:**
|
|
```bash
|
|
curl -s http://localhost:8080/api/health
|
|
# Should return connection refused
|
|
```
|
|
|
|
## 🌐 API Endpoints
|
|
|
|
### Base URL
|
|
```
|
|
http://localhost:8080
|
|
```
|
|
|
|
### Health Check
|
|
```http
|
|
GET /api/health
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{"status":"healthy"}
|
|
```
|
|
|
|
### Readiness Check
|
|
```http
|
|
GET /api/ready
|
|
```
|
|
|
|
**Responses:**
|
|
- Normal operation: `{"ready":true}` (HTTP 200)
|
|
- During shutdown: `{"ready":false}` (HTTP 503 Service Unavailable)
|
|
|
|
**Purpose:** Indicates whether the server is ready to accept new requests. Returns false during graceful shutdown to allow existing requests to complete while preventing new ones.
|
|
|
|
### Greet Service
|
|
```http
|
|
GET /api/v1/greet/
|
|
GET /api/v1/greet/{name}
|
|
```
|
|
|
|
**Examples:**
|
|
```bash
|
|
# Default greeting
|
|
curl http://localhost:8080/api/v1/greet/
|
|
# Response: {"message":"Hello world!"}
|
|
|
|
# Personalized greeting
|
|
curl http://localhost:8080/api/v1/greet/John
|
|
# Response: {"message":"Hello John!"}
|
|
|
|
# Another example
|
|
curl http://localhost:8080/api/v1/greet/Alice
|
|
# Response: {"message":"Hello Alice!"}
|
|
```
|
|
|
|
## 🔧 Development Workflow
|
|
|
|
### 1. Check Server Status
|
|
```bash
|
|
curl -s http://localhost:8080/api/health
|
|
```
|
|
|
|
### 2. Start Development Server
|
|
```bash
|
|
cd /Users/gabrielradureau/Work/Vibe/DanceLessonsCoach
|
|
go run cmd/server/main.go &
|
|
```
|
|
|
|
### 3. Test API Endpoints
|
|
```bash
|
|
# Test all endpoints as shown above
|
|
curl http://localhost:8080/api/v1/greet/YourName
|
|
```
|
|
|
|
### 4. Run Tests
|
|
```bash
|
|
# Run all tests
|
|
go test ./...
|
|
|
|
# Run specific package
|
|
go test ./pkg/greet/
|
|
```
|
|
|
|
### 5. Make Changes
|
|
- Edit source files in `pkg/` or `cmd/`
|
|
- Follow existing patterns and interfaces
|
|
- Add tests for new functionality
|
|
|
|
### 6. Stop and Restart
|
|
```bash
|
|
pkill -f "go"
|
|
go run cmd/server/main.go &
|
|
```
|
|
|
|
## 🧪 Testing
|
|
|
|
### Unit Tests
|
|
```bash
|
|
# Run all tests
|
|
go test ./...
|
|
|
|
# Run with verbose output
|
|
go test -v ./...
|
|
|
|
# Run specific test
|
|
go test ./pkg/greet/ -run TestService_Greet
|
|
```
|
|
|
|
### CLI Testing
|
|
```bash
|
|
# Default greeting
|
|
go run ./cmd/greet
|
|
# Output: Hello world!
|
|
|
|
# Personalized greeting
|
|
go run ./cmd/greet John
|
|
# Output: Hello John!
|
|
```
|
|
|
|
### API Testing
|
|
```bash
|
|
# Health check
|
|
curl http://localhost:8080/api/health
|
|
|
|
# Greet endpoints
|
|
curl http://localhost:8080/api/v1/greet/John
|
|
curl http://localhost:8080/api/v1/greet/
|
|
```
|
|
|
|
## 📝 Architecture Decisions
|
|
|
|
### Interface-Based Design
|
|
```go
|
|
type Greeter interface {
|
|
Greet(ctx context.Context, name string) string
|
|
}
|
|
```
|
|
|
|
**Benefits:**
|
|
- Easy mocking for tests
|
|
- Dependency injection
|
|
- Multiple implementations
|
|
- Clear contracts
|
|
|
|
### Context-Aware Services
|
|
```go
|
|
func (s *Service) Greet(ctx context.Context, name string) string {
|
|
log.Trace().Ctx(ctx).Str("name", name).Msg("Greet function called")
|
|
// ...
|
|
}
|
|
```
|
|
|
|
**Benefits:**
|
|
- Request tracing
|
|
- Cancellation support
|
|
- Deadline propagation
|
|
- Metadata passing
|
|
|
|
### Server Context Management
|
|
```go
|
|
// Root context with cancellation
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
// Server context with graceful shutdown
|
|
serverCtx, serverStop := context.WithCancel(ctx)
|
|
|
|
// HTTP server with context-aware shutdown
|
|
srv := &http.Server{
|
|
Addr: ":8080",
|
|
Handler: server.Router(),
|
|
}
|
|
|
|
// Graceful shutdown with timeout
|
|
shutdownCtx, shutdownCancel := context.WithTimeout(
|
|
context.Background(),
|
|
30*time.Second
|
|
)
|
|
defer shutdownCancel()
|
|
|
|
if err := srv.Shutdown(shutdownCtx); err != nil {
|
|
log.Error().Err(err).Msg("Server shutdown failed")
|
|
}
|
|
```
|
|
|
|
**Benefits:**
|
|
- Graceful shutdown handling
|
|
- Signal-based termination (SIGINT, SIGTERM)
|
|
- 30-second timeout for active connections
|
|
- Proper resource cleanup
|
|
- Context propagation throughout server lifecycle
|
|
|
|
### Zerolog Logging
|
|
```go
|
|
zerolog.SetGlobalLevel(zerolog.TraceLevel)
|
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
|
```
|
|
|
|
**Benefits:**
|
|
- High performance
|
|
- Structured logging
|
|
- Trace level detail
|
|
- Color output
|
|
|
|
### Versioned API
|
|
```go
|
|
router.Route("/api/v1", func(r chi.Router) {
|
|
// v1 endpoints
|
|
})
|
|
```
|
|
|
|
**Benefits:**
|
|
- Backward compatibility
|
|
- Clear versioning
|
|
- Easy migration
|
|
- Parallel versions
|
|
|
|
## 🔍 Troubleshooting
|
|
|
|
### Port Already in Use
|
|
```bash
|
|
# Find and kill process using port 8080
|
|
kill -TERM $(lsof -ti :8080)
|
|
```
|
|
|
|
### Server Not Responding
|
|
```bash
|
|
# Check if running
|
|
curl -s http://localhost:8080/api/health
|
|
|
|
# Restart server
|
|
pkill -f "go"
|
|
go run cmd/server/main.go &
|
|
```
|
|
|
|
### Dependency Issues
|
|
```bash
|
|
# Clean and rebuild
|
|
go mod tidy
|
|
go build ./...
|
|
```
|
|
|
|
### Tests Failing
|
|
```bash
|
|
# Run with verbose output
|
|
go test -v ./...
|
|
|
|
# Check specific test
|
|
go test ./pkg/greet/ -run TestName
|
|
```
|
|
|
|
## 📚 Code Examples
|
|
|
|
### Adding New API Endpoint
|
|
```go
|
|
// 1. Add to interface
|
|
func (h *apiV1GreetHandler) RegisterRoutes(router chi.Router) {
|
|
router.Get("/", h.handleGreetQuery)
|
|
router.Get("/{name}", h.handleGreetPath)
|
|
router.Post("/custom", h.handleCustomGreet) // New endpoint
|
|
}
|
|
|
|
// 2. Implement handler
|
|
func (h *apiV1GreetHandler) handleCustomGreet(w http.ResponseWriter, r *http.Request) {
|
|
// Parse request
|
|
// Call service
|
|
// Return JSON response
|
|
}
|
|
```
|
|
|
|
### Adding Logging
|
|
```go
|
|
// Trace level logging
|
|
log.Trace().Ctx(ctx).Str("key", "value").Msg("message")
|
|
|
|
// Info level
|
|
log.Info().Msg("Important event")
|
|
|
|
// Error level
|
|
log.Error().Err(err).Msg("Error occurred")
|
|
```
|
|
|
|
### Using Context
|
|
```go
|
|
// Pass context through calls
|
|
func handler(w http.ResponseWriter, r *http.Request) {
|
|
result := service.Greet(r.Context(), "John")
|
|
// ...
|
|
}
|
|
|
|
// Create context with values
|
|
ctx := context.WithValue(r.Context(), "key", "value")
|
|
|
|
// Create context with timeout
|
|
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
|
|
defer cancel()
|
|
```
|
|
|
|
## 🎓 Best Practices
|
|
|
|
### Code Organization
|
|
- Keep handlers thin, move logic to services
|
|
- Use interfaces for dependencies
|
|
- Separate route registration from handlers
|
|
- Group related functionality
|
|
|
|
### Error Handling
|
|
- Return proper HTTP status codes
|
|
- Log errors with context
|
|
- Don't expose internal errors to clients
|
|
- Use structured error responses
|
|
|
|
### Performance
|
|
- Use Zerolog's Trace level sparingly in production
|
|
- Avoid allocations in hot paths
|
|
- Use context timeouts for external calls
|
|
- Batch database operations
|
|
|
|
### Testing
|
|
- Test interfaces, not implementations
|
|
- Use table-driven tests
|
|
- Test error cases
|
|
- Mock dependencies
|
|
|
|
## 📈 Future Enhancements
|
|
|
|
### Potential Features
|
|
- [ ] Configuration management
|
|
- [ ] Database integration
|
|
- [ ] Authentication/Authorization
|
|
- [ ] Rate limiting
|
|
- [ ] Metrics and monitoring
|
|
- [ ] Docker containerization
|
|
- [ ] CI/CD pipeline
|
|
|
|
### Architectural Improvements
|
|
- [ ] Request validation middleware
|
|
- [ ] OpenAPI/Swagger documentation
|
|
- [ ] Graceful shutdown
|
|
- [ ] Configuration hot reload
|
|
- [ ] Circuit breakers
|
|
|
|
## 📝 Changelog
|
|
|
|
### 2026-04-03 - Current Version
|
|
- ✅ Zerolog integration with Trace level
|
|
- ✅ Context-aware Greet service
|
|
- ✅ Fixed route structure `/api/v1/greet/*`
|
|
- ✅ Comprehensive server management guide
|
|
- ✅ Verified all API endpoints working
|
|
- ✅ Updated documentation
|
|
|
|
### 2026-04-02 - Web API Implementation
|
|
- ✅ Chi router integration
|
|
- ✅ Versioned API endpoints
|
|
- ✅ JSON responses
|
|
- ✅ Health endpoint
|
|
- ✅ Interface-based design
|
|
|
|
### 2026-04-01 - Foundation
|
|
- ✅ Go 1.26.1 setup
|
|
- ✅ Project structure
|
|
- ✅ Core Greet service
|
|
- ✅ CLI interface
|
|
- ✅ Unit tests
|
|
|
|
## 🤖 AI Agent Information
|
|
|
|
**Agent:** Mistral Vibe CLI Agent
|
|
**Version:** devstral-2
|
|
**Role:** Development Assistant
|
|
**Capabilities:**
|
|
- Code generation and refactoring
|
|
- Test creation
|
|
- Documentation
|
|
- Architecture guidance
|
|
- Best practices enforcement
|
|
|
|
## 📋 Quick Reference
|
|
|
|
### Common Commands
|
|
```bash
|
|
# Start server
|
|
go run cmd/server/main.go &
|
|
|
|
# Test API
|
|
curl http://localhost:8080/api/v1/greet/John
|
|
|
|
# Run tests
|
|
go test ./...
|
|
|
|
# Stop server
|
|
pkill -f "go"
|
|
|
|
# CLI usage
|
|
go run ./cmd/greet John
|
|
```
|
|
|
|
### Project Structure
|
|
```
|
|
cmd/ # Entry points
|
|
pkg/ # Core logic
|
|
greet/ # Domain services
|
|
server/ # HTTP server
|
|
go.mod # Dependencies
|
|
README.md # User docs
|
|
AGENTS.md # This file
|
|
```
|
|
|
|
### Key Interfaces
|
|
```go
|
|
type Greeter interface {
|
|
Greet(ctx context.Context, name string) string
|
|
}
|
|
|
|
type ApiV1Greet interface {
|
|
RegisterRoutes(router chi.Router)
|
|
}
|
|
```
|
|
|
|
## 📞 Support
|
|
|
|
For issues or questions:
|
|
1. Check this documentation
|
|
2. Review test cases
|
|
3. Examine existing implementations
|
|
4. Consult Go and Chi documentation
|
|
5. Ask the AI agent for guidance
|
|
|
|
This documentation provides a complete guide to developing, testing, and maintaining the DanceLessonsCoach project using the established patterns and best practices. |