control/controlclient: introduce eventbus messages instead of callbacks (#16956)
This is a small introduction of the eventbus into controlclient that communicates with mainly ipnlocal. While ipnlocal is a complicated part of the codebase, the subscribers here are from the perspective of ipnlocal already called async. Updates #15160 Signed-off-by: Claus Lensbøl <claus@tailscale.com>
This commit is contained in:
+41
-2
@@ -6,12 +6,14 @@ package ipnlocal
|
||||
import (
|
||||
"time"
|
||||
|
||||
"tailscale.com/control/controlclient"
|
||||
"tailscale.com/syncs"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/tstime"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/types/netmap"
|
||||
"tailscale.com/util/eventbus"
|
||||
)
|
||||
|
||||
// For extra defense-in-depth, when we're testing expired nodes we check
|
||||
@@ -40,14 +42,46 @@ type expiryManager struct {
|
||||
|
||||
logf logger.Logf
|
||||
clock tstime.Clock
|
||||
|
||||
eventClient *eventbus.Client
|
||||
controlTimeSub *eventbus.Subscriber[controlclient.ControlTime]
|
||||
subsDoneCh chan struct{} // closed when consumeEventbusTopics returns
|
||||
}
|
||||
|
||||
func newExpiryManager(logf logger.Logf) *expiryManager {
|
||||
return &expiryManager{
|
||||
func newExpiryManager(logf logger.Logf, bus *eventbus.Bus) *expiryManager {
|
||||
em := &expiryManager{
|
||||
previouslyExpired: map[tailcfg.StableNodeID]bool{},
|
||||
logf: logf,
|
||||
clock: tstime.StdClock{},
|
||||
}
|
||||
|
||||
em.eventClient = bus.Client("ipnlocal.expiryManager")
|
||||
em.controlTimeSub = eventbus.Subscribe[controlclient.ControlTime](em.eventClient)
|
||||
|
||||
em.subsDoneCh = make(chan struct{})
|
||||
go em.consumeEventbusTopics()
|
||||
|
||||
return em
|
||||
}
|
||||
|
||||
// consumeEventbusTopics consumes events from all relevant
|
||||
// [eventbus.Subscriber]'s and passes them to their related handler. Events are
|
||||
// always handled in the order they are received, i.e. the next event is not
|
||||
// read until the previous event's handler has returned. It returns when the
|
||||
// [controlclient.ControlTime] subscriber is closed, which is interpreted to be the
|
||||
// same as the [eventbus.Client] closing ([eventbus.Subscribers] are either
|
||||
// all open or all closed).
|
||||
func (em *expiryManager) consumeEventbusTopics() {
|
||||
defer close(em.subsDoneCh)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-em.controlTimeSub.Done():
|
||||
return
|
||||
case time := <-em.controlTimeSub.Events():
|
||||
em.onControlTime(time.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// onControlTime is called whenever we receive a new timestamp from the control
|
||||
@@ -218,6 +252,11 @@ func (em *expiryManager) nextPeerExpiry(nm *netmap.NetworkMap, localNow time.Tim
|
||||
return nextExpiry
|
||||
}
|
||||
|
||||
func (em *expiryManager) close() {
|
||||
em.eventClient.Close()
|
||||
<-em.subsDoneCh
|
||||
}
|
||||
|
||||
// ControlNow estimates the current time on the control server, calculated as
|
||||
// localNow + the delta between local and control server clocks as recorded
|
||||
// when the LocalBackend last received a time message from the control server.
|
||||
|
||||
Reference in New Issue
Block a user