返回 DeepSeek-Reasonix
status.go
根目录 / internal / remote / status.go
1 package remote
2
3 import "sync"
4
5 // statusHub fans status events out to subscribers and remembers the last event
6 // so a late subscriber immediately learns the current state. Subscriber
7 // callbacks are invoked synchronously under no lock; they must not block or
8 // call back into the Client.
9 type statusHub struct {
10 mu sync.Mutex
11 last StatusEvent
12 haveL bool
13 nextID int
14 subs map[int]func(StatusEvent)
15 }
16
17 func newStatusHub() *statusHub {
18 return &statusHub{subs: map[int]func(StatusEvent){}}
19 }
20
21 // subscribe registers fn, replays the last event to it, and returns a cancel.
22 func (h *statusHub) subscribe(fn func(StatusEvent)) func() {
23 h.mu.Lock()
24 id := h.nextID
25 h.nextID++
26 h.subs[id] = fn
27 last, have := h.last, h.haveL
28 h.mu.Unlock()
29
30 if have {
31 fn(last)
32 }
33 return func() {
34 h.mu.Lock()
35 delete(h.subs, id)
36 h.mu.Unlock()
37 }
38 }
39
40 // publish records ev as the last event and delivers it to all subscribers.
41 func (h *statusHub) publish(ev StatusEvent) {
42 h.mu.Lock()
43 h.last = ev
44 h.haveL = true
45 fns := make([]func(StatusEvent), 0, len(h.subs))
46 for _, fn := range h.subs {
47 fns = append(fns, fn)
48 }
49 h.mu.Unlock()
50 for _, fn := range fns {
51 fn(ev)
52 }
53 }
54
55 func (h *statusHub) current() StatusEvent {
56 h.mu.Lock()
57 defer h.mu.Unlock()
58 return h.last
59 }
60
60 lines GO