fix: Address CodeRabbit review findings

- Create api/swagger.md page to properly document Swagger UI access
  instead of linking raw swagger.json in mkdocs nav
- Fix Stop() state management: properly set Running=false and cmd=nil
  on all exit paths, wait for process termination to avoid zombies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
snider 2025-12-31 01:28:01 +00:00
parent f2afdeeb82
commit 9592971678
3 changed files with 84 additions and 6 deletions

62
docs/api/swagger.md Normal file
View file

@ -0,0 +1,62 @@
# Swagger Documentation
Interactive API documentation is available when running the Mining service.
## Accessing Swagger UI
When the service is running, you can access the Swagger UI at:
```
http://localhost:9090/api/v1/mining/swagger/index.html
```
## Starting the Service
=== "CLI"
```bash
miner-ctrl serve
```
=== "Development"
```bash
make dev
```
## OpenAPI Specification
The OpenAPI 3.0 specification is available at:
- **JSON**: `http://localhost:9090/api/v1/mining/swagger/doc.json`
- **YAML**: `http://localhost:9090/api/v1/mining/swagger/doc.yaml`
## Regenerating Docs
After modifying API endpoints, regenerate the Swagger documentation:
```bash
make docs
```
This runs `swag init` to parse the Go annotations and update the specification files.
## API Annotations
API documentation is generated from Go comments using [swaggo/swag](https://github.com/swaggo/swag). Example:
```go
// StartMiner godoc
// @Summary Start a miner
// @Description Start mining with a specific profile
// @Tags miners
// @Accept json
// @Produce json
// @Param profile_id path string true "Profile ID"
// @Success 200 {object} MinerResponse
// @Failure 400 {object} ErrorResponse
// @Router /miners/{profile_id}/start [post]
func (s *Service) StartMiner(c *gin.Context) {
// ...
}
```

View file

@ -150,7 +150,7 @@ nav:
- API Reference: - API Reference:
- Overview: api/index.md - Overview: api/index.md
- Endpoints: api/endpoints.md - Endpoints: api/endpoints.md
- Swagger Docs: swagger.json - Swagger Docs: api/swagger.md
- Development: - Development:
- Setup: development/index.md - Setup: development/index.md

View file

@ -144,26 +144,42 @@ func (b *BaseMiner) Stop() error {
b.stdinPipe = nil b.stdinPipe = nil
} }
// Helper to clean up state
cleanup := func() {
b.Running = false
b.cmd = nil
}
// Try graceful shutdown with SIGTERM first (Unix only) // Try graceful shutdown with SIGTERM first (Unix only)
if runtime.GOOS != "windows" { if runtime.GOOS != "windows" {
if err := b.cmd.Process.Signal(syscall.SIGTERM); err == nil { if err := b.cmd.Process.Signal(syscall.SIGTERM); err == nil {
// Wait up to 3 seconds for graceful shutdown // Wait up to 3 seconds for graceful shutdown
done := make(chan error, 1) done := make(chan struct{})
go func() { go func() {
_, err := b.cmd.Process.Wait() b.cmd.Process.Wait()
done <- err close(done)
}() }()
select { select {
case <-done: case <-done:
cleanup()
return nil return nil
case <-time.After(3 * time.Second): case <-time.After(3 * time.Second):
// Process didn't exit, force kill // Process didn't exit gracefully, force kill below
} }
} }
} }
return b.cmd.Process.Kill() // Force kill and wait for process to exit
if err := b.cmd.Process.Kill(); err != nil {
cleanup()
return err
}
// Wait for process to fully terminate to avoid zombies
b.cmd.Process.Wait()
cleanup()
return nil
} }
// WriteStdin sends input to the miner's stdin (for console commands). // WriteStdin sends input to the miner's stdin (for console commands).