The node agent waits for a backup's end on the holder's event, not by polling; the manifest consumes it (R6-A A5)

This commit is contained in:
2026-10-24 17:03:30 +02:00
parent 20d0998cdd
commit e5a06cc73d
6 changed files with 158 additions and 53 deletions
+47
View File
@@ -127,3 +127,50 @@ func (q *Session) WhenLinked(ctx context.Context) (context.Context, context.Canc
}
}
}
// EventBus is a link that can hear an event on a subject of core NATS: the node agent waits for a backup's end with it,
// and never polls.
type EventBus interface {
// Hear yields the payloads published on the subject until stop is called or the link ends.
Hear(subject string) (events <-chan []byte, stop func(), err error)
}
func (b OverNATS) Hear(subject string) (<-chan []byte, func(), error) {
out := make(chan []byte, 16)
sub, err := b.Conn.Subscribe(subject, func(m *nats.Msg) {
select {
case out <- m.Data:
default:
}
})
if err != nil {
return nil, nil, err
}
if err := b.Conn.Flush(); err != nil {
_ = sub.Unsubscribe()
return nil, nil, err
}
return out, func() { _ = sub.Unsubscribe() }, nil
}
func (l *natsLink) Hear(subject string) (<-chan []byte, func(), error) {
return OverNATS{Conn: l.conn, JS: l.js}.Hear(subject)
}
var (
_ EventBus = OverNATS{}
_ EventBus = (*natsLink)(nil)
)
// Hear listens for an event on the link open now, from before the caller asks for what it waits on.
func (q *Session) Hear(subject string) (<-chan []byte, func(), error) {
q.init()
q.mu.Lock()
bus := q.bus
q.mu.Unlock()
h, ok := bus.(EventBus)
if bus == nil || !ok {
return nil, nil, ErrNoLink
}
return h.Hear(subject)
}