mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
87257819f6
- track boot and config default models in gateway status/events - preserve running, starting, and restarting states during health checks - add safer gateway restart handling with stronger backend test coverage - expose restart-required UI and refresh model state after default model update
66 lines
1.6 KiB
Go
66 lines
1.6 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sync"
|
|
)
|
|
|
|
// GatewayEvent represents a state change event for the gateway process.
|
|
type GatewayEvent struct {
|
|
Status string `json:"gateway_status"` // "running", "starting", "restarting", "stopped", "error"
|
|
PID int `json:"pid,omitempty"`
|
|
BootDefaultModel string `json:"boot_default_model,omitempty"`
|
|
ConfigDefaultModel string `json:"config_default_model,omitempty"`
|
|
RestartRequired bool `json:"gateway_restart_required,omitempty"`
|
|
}
|
|
|
|
// EventBroadcaster manages SSE client subscriptions and broadcasts events.
|
|
type EventBroadcaster struct {
|
|
mu sync.RWMutex
|
|
clients map[chan string]struct{}
|
|
}
|
|
|
|
// NewEventBroadcaster creates a new broadcaster.
|
|
func NewEventBroadcaster() *EventBroadcaster {
|
|
return &EventBroadcaster{
|
|
clients: make(map[chan string]struct{}),
|
|
}
|
|
}
|
|
|
|
// Subscribe adds a new listener channel and returns it.
|
|
// The caller must call Unsubscribe when done.
|
|
func (b *EventBroadcaster) Subscribe() chan string {
|
|
ch := make(chan string, 8)
|
|
b.mu.Lock()
|
|
b.clients[ch] = struct{}{}
|
|
b.mu.Unlock()
|
|
return ch
|
|
}
|
|
|
|
// Unsubscribe removes a listener channel and closes it.
|
|
func (b *EventBroadcaster) Unsubscribe(ch chan string) {
|
|
b.mu.Lock()
|
|
delete(b.clients, ch)
|
|
b.mu.Unlock()
|
|
close(ch)
|
|
}
|
|
|
|
// Broadcast sends a GatewayEvent to all connected SSE clients.
|
|
func (b *EventBroadcaster) Broadcast(event GatewayEvent) {
|
|
data, err := json.Marshal(event)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
b.mu.RLock()
|
|
defer b.mu.RUnlock()
|
|
|
|
for ch := range b.clients {
|
|
// Non-blocking send; drop event if client is slow
|
|
select {
|
|
case ch <- string(data):
|
|
default:
|
|
}
|
|
}
|
|
}
|