Fix group status updates broken by API service
The URL test history update hook and the Clash mode update hook were single-slot: the API service's attached service overwrote the hook set by the daemon, so clients stopped receiving group updates. Replace both with multicast hook lists. Also share a single URL test history storage via context: Clash API looked it up under a key nobody registered and fell back to its own empty storage, so dashboards showed no delay once an API service was configured. Selector changes now notify through the shared storage, covering selections made from any API surface.
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/adapter/outbound"
|
||||
"github.com/sagernet/sing-box/common/interrupt"
|
||||
"github.com/sagernet/sing-box/common/urltest"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
@@ -40,6 +41,7 @@ type Selector struct {
|
||||
defaultTag string
|
||||
outbounds map[string]adapter.Outbound
|
||||
selected common.TypedValue[adapter.Outbound]
|
||||
history *urltest.HistoryStorage
|
||||
interruptGroup *interrupt.Group
|
||||
interruptExternalConnections bool
|
||||
}
|
||||
@@ -54,6 +56,7 @@ func NewSelector(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
tags: options.Outbounds,
|
||||
defaultTag: options.Default,
|
||||
outbounds: make(map[string]adapter.Outbound),
|
||||
history: service.PtrFromContext[urltest.HistoryStorage](ctx),
|
||||
interruptGroup: interrupt.NewGroup(),
|
||||
interruptExternalConnections: options.InterruptExistConnections,
|
||||
}
|
||||
@@ -137,6 +140,9 @@ func (s *Selector) SelectOutbound(tag string) bool {
|
||||
}
|
||||
}
|
||||
s.interruptGroup.Interrupt(s.interruptExternalConnections)
|
||||
if s.history != nil {
|
||||
s.history.NotifyUpdated()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ type URLTestGroup struct {
|
||||
interval time.Duration
|
||||
tolerance uint16
|
||||
idleTimeout time.Duration
|
||||
history adapter.URLTestHistoryStorage
|
||||
history *urltest.HistoryStorage
|
||||
checking atomic.Bool
|
||||
selectedOutboundTCP adapter.Outbound
|
||||
selectedOutboundUDP adapter.Outbound
|
||||
@@ -221,13 +221,9 @@ func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManage
|
||||
if interval > idleTimeout {
|
||||
return nil, E.New("interval must be less or equal than idle_timeout")
|
||||
}
|
||||
var history adapter.URLTestHistoryStorage
|
||||
if historyFromCtx := service.PtrFromContext[urltest.HistoryStorage](ctx); historyFromCtx != nil {
|
||||
history = historyFromCtx
|
||||
} else if clashServer := service.FromContext[adapter.ClashServer](ctx); clashServer != nil {
|
||||
history = clashServer.HistoryStorage()
|
||||
} else {
|
||||
history = urltest.NewHistoryStorage()
|
||||
history := service.PtrFromContext[urltest.HistoryStorage](ctx)
|
||||
if history == nil {
|
||||
return nil, E.New("missing URL test history storage")
|
||||
}
|
||||
return &URLTestGroup{
|
||||
ctx: ctx,
|
||||
|
||||
Reference in New Issue
Block a user