feat: auto-register/unregister daemons via optional Registry
When Registry is set on DaemonOptions, Start() auto-registers the daemon (filling PID and Health address) and Stop() auto-unregisters it. Consumers without a registry are completely unaffected. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2a26948d44
commit
81de841903
2 changed files with 56 additions and 0 deletions
25
daemon.go
25
daemon.go
|
|
@ -26,6 +26,13 @@ type DaemonOptions struct {
|
|||
|
||||
// HealthChecks are additional health check functions.
|
||||
HealthChecks []HealthCheck
|
||||
|
||||
// Registry for tracking this daemon. Leave nil to skip registration.
|
||||
Registry *Registry
|
||||
|
||||
// RegistryEntry provides the code and daemon name for registration.
|
||||
// PID, Health, and Started are filled automatically.
|
||||
RegistryEntry DaemonEntry
|
||||
}
|
||||
|
||||
// Daemon manages daemon lifecycle: PID file, health server, graceful shutdown.
|
||||
|
|
@ -84,6 +91,19 @@ func (d *Daemon) Start() error {
|
|||
}
|
||||
|
||||
d.running = true
|
||||
|
||||
// Auto-register if registry is set
|
||||
if d.opts.Registry != nil {
|
||||
entry := d.opts.RegistryEntry
|
||||
entry.PID = os.Getpid()
|
||||
if d.health != nil {
|
||||
entry.Health = d.health.Addr()
|
||||
}
|
||||
if err := d.opts.Registry.Register(entry); err != nil {
|
||||
return fmt.Errorf("registry: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -128,6 +148,11 @@ func (d *Daemon) Stop() error {
|
|||
}
|
||||
}
|
||||
|
||||
// Auto-unregister
|
||||
if d.opts.Registry != nil {
|
||||
_ = d.opts.Registry.Unregister(d.opts.RegistryEntry.Code, d.opts.RegistryEntry.Daemon)
|
||||
}
|
||||
|
||||
d.running = false
|
||||
|
||||
if len(errs) > 0 {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package process
|
|||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
|
@ -91,3 +92,33 @@ func TestDaemon_DefaultShutdownTimeout(t *testing.T) {
|
|||
d := NewDaemon(DaemonOptions{})
|
||||
assert.Equal(t, 30*time.Second, d.opts.ShutdownTimeout)
|
||||
}
|
||||
|
||||
func TestDaemon_AutoRegisters(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
reg := NewRegistry(filepath.Join(dir, "daemons"))
|
||||
|
||||
d := NewDaemon(DaemonOptions{
|
||||
HealthAddr: "127.0.0.1:0",
|
||||
Registry: reg,
|
||||
RegistryEntry: DaemonEntry{
|
||||
Code: "test-app",
|
||||
Daemon: "serve",
|
||||
},
|
||||
})
|
||||
|
||||
err := d.Start()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Should be registered
|
||||
entry, ok := reg.Get("test-app", "serve")
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, os.Getpid(), entry.PID)
|
||||
assert.NotEmpty(t, entry.Health)
|
||||
|
||||
// Stop should unregister
|
||||
err = d.Stop()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, ok = reg.Get("test-app", "serve")
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue