Files
next.orly.dev/pkg/utils/interrupt/README.md
mleku e56bf76257
Some checks failed
Go / build (push) Has been cancelled
Go / release (push) Has been cancelled
Add NIP-11 relay synchronization and group management features
- Introduced a new `sync` package for managing NIP-11 relay information and relay group configurations.
- Implemented a cache for NIP-11 documents, allowing retrieval of relay public keys and authoritative configurations.
- Enhanced the sync manager to update peer lists based on authoritative configurations from relay group events.
- Updated event handling to incorporate policy checks during event imports, ensuring compliance with relay rules.
- Refactored various components to utilize the new `sha256-simd` package for improved performance.
- Added comprehensive tests to validate the new synchronization and group management functionalities.
- Bumped version to v0.24.1 to reflect these changes.
2025-11-03 18:17:15 +00:00

292 lines
5.6 KiB
Markdown

# interrupt
Graceful shutdown handling for Go applications. This package provides utilities for handling OS signals (SIGINT, SIGTERM) to enable clean shutdowns and hot reloading capabilities.
## Features
- **Signal Handling**: Clean handling of SIGINT, SIGTERM, and SIGHUP signals
- **Graceful Shutdown**: Allows running goroutines to finish before exit
- **Hot Reload Support**: Trigger application reloads on SIGHUP
- **Context Integration**: Works seamlessly with Go's context package
- **Custom Callbacks**: Execute custom cleanup logic during shutdown
- **Non-blocking**: Doesn't block the main application loop
## Installation
```bash
go get next.orly.dev/pkg/utils/interrupt
```
## Usage
### Basic Shutdown Handling
```go
package main
import (
"context"
"log"
"time"
"next.orly.dev/pkg/utils/interrupt"
)
func main() {
// Create interrupt handler
handler := interrupt.New()
// Start your application
go func() {
for {
select {
case <-handler.Shutdown():
log.Println("Shutting down worker...")
return
default:
// Do work
time.Sleep(time.Second)
}
}
}()
// Wait for shutdown signal
<-handler.Done()
log.Println("Application stopped")
}
```
### Context Integration
```go
func worker(ctx context.Context) {
handler := interrupt.New()
// Create context that cancels on shutdown
workCtx, cancel := context.WithCancel(ctx)
defer cancel()
go func() {
<-handler.Shutdown()
cancel()
}()
// Use workCtx for all operations
for {
select {
case <-workCtx.Done():
return
default:
// Do work with context
}
}
}
```
### Custom Shutdown Callbacks
```go
handler := interrupt.New()
// Add cleanup callbacks
handler.OnShutdown(func() {
log.Println("Closing database connections...")
db.Close()
})
handler.OnShutdown(func() {
log.Println("Saving application state...")
saveState()
})
// Callbacks execute in reverse order when shutdown occurs
<-handler.Done()
```
### Hot Reload Support
```go
handler := interrupt.New()
// Handle reload signals
go func() {
for {
select {
case <-handler.Reload():
log.Println("Reloading configuration...")
reloadConfig()
case <-handler.Shutdown():
return
}
}
}()
<-handler.Done()
```
## API Reference
### Handler
The main interrupt handler type.
**Methods:**
- `New() *Handler` - Create a new interrupt handler
- `Shutdown() <-chan struct{}` - Channel closed on shutdown signals
- `Reload() <-chan struct{}` - Channel closed on reload signals (SIGHUP)
- `Done() <-chan struct{}` - Channel closed when all cleanup is complete
- `OnShutdown(func())` - Add a callback to run during shutdown
- `Wait()` - Block until shutdown signal received
- `IsShuttingDown() bool` - Check if shutdown is in progress
### Signal Handling
The package handles these signals:
- **SIGINT**: Interrupt (Ctrl+C) - Triggers graceful shutdown
- **SIGTERM**: Termination - Triggers graceful shutdown
- **SIGHUP**: Hangup - Triggers reload (can be customized)
### Shutdown Process
1. Signal received (SIGINT/SIGTERM)
2. Shutdown callbacks execute (in reverse order added)
3. Shutdown channel closes
4. Application can perform final cleanup
5. Done channel closes
## Testing
The interrupt package includes comprehensive tests:
### Running Tests
```bash
# Run interrupt package tests
go test ./pkg/utils/interrupt
# Run with verbose output
go test -v ./pkg/utils/interrupt
# Run with race detection
go test -race ./pkg/utils/interrupt
```
### Integration Testing
Part of the full test suite:
```bash
# Run all tests including interrupt
./scripts/test.sh
# Run specific package tests
go test ./pkg/utils/...
```
### Test Coverage
Tests cover:
- Signal handling for all supported signals
- Callback execution order and timing
- Context cancellation
- Concurrent access patterns
- Race condition prevention
### Example Test
```bash
# Test signal handling
go test -v ./pkg/utils/interrupt -run TestSignalHandling
# Test callback execution
go test -v ./pkg/utils/interrupt -run TestShutdownCallbacks
```
## Examples
### HTTP Server with Graceful Shutdown
```go
package main
import (
"context"
"log"
"net/http"
"time"
"next.orly.dev/pkg/utils/interrupt"
)
func main() {
handler := interrupt.New()
server := &http.Server{
Addr: ":8080",
Handler: http.DefaultServeMux,
}
// Shutdown server gracefully
handler.OnShutdown(func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
server.Shutdown(ctx)
})
go server.ListenAndServe()
<-handler.Done()
log.Println("Server stopped")
}
```
### Worker Pool with Cleanup
```go
func main() {
handler := interrupt.New()
// Start worker pool
pool := NewWorkerPool(10)
pool.Start()
// Clean shutdown
handler.OnShutdown(func() {
log.Println("Stopping worker pool...")
pool.Stop()
})
<-handler.Done()
}
```
## Development
### Building
```bash
go build ./pkg/utils/interrupt
```
### Code Quality
- Comprehensive test coverage
- Go best practices compliance
- Thread-safe design
- Proper signal handling
- No external dependencies
## Integration
This package integrates well with:
- HTTP servers (graceful shutdown)
- Database connections (cleanup)
- Worker pools (coordination)
- Long-running services (reload capability)
## License
Part of the next.orly.dev project. See main LICENSE file.