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:
parent
f2afdeeb82
commit
9592971678
3 changed files with 84 additions and 6 deletions
62
docs/api/swagger.md
Normal file
62
docs/api/swagger.md
Normal 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) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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).
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue