From 61431801ea5805fbe2530b3bae68d94b8ae4aa25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Papp?= Date: Fri, 29 May 2026 14:58:17 +0200 Subject: [PATCH] ui: extract subscribeAndStreamEvents to cut toastStreamLoop complexity Move the event backoff op body into subscribeAndStreamEvents and the per-event fan-out into dispatchSystemEvent, bringing toastStreamLoop under the 20 cognitive-complexity limit. No behavior change. --- client/ui/services/daemon_feed.go | 66 +++++++++++++++++++------------ 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/client/ui/services/daemon_feed.go b/client/ui/services/daemon_feed.go index 58c03920e..19c28a831 100644 --- a/client/ui/services/daemon_feed.go +++ b/client/ui/services/daemon_feed.go @@ -415,32 +415,7 @@ func (s *DaemonFeed) toastStreamLoop(ctx context.Context) { }, ctx) op := func() error { - cli, err := s.conn.Client() - if err != nil { - return fmt.Errorf("get client: %w", err) - } - stream, err := cli.SubscribeEvents(ctx, &proto.SubscribeRequest{}) - if err != nil { - return fmt.Errorf("subscribe: %w", err) - } - for { - ev, err := stream.Recv() - if err != nil { - if ctx.Err() != nil { - return ctx.Err() - } - return fmt.Errorf("stream recv: %w", err) - } - se := systemEventFromProto(ev) - log.Infof("backend event: system severity=%s category=%s msg=%q", se.Severity, se.Category, se.UserMessage) - s.emitter.Emit(EventDaemonNotification, se) - if warn, ok := authsession.WarningFromMetadata(se.Metadata); ok { - s.emitter.Emit(EventSessionWarning, warn) - } - if s.updater != nil { - s.updater.OnSystemEvent(ev) - } - } + return s.subscribeAndStreamEvents(ctx) } if err := backoff.Retry(op, bo); err != nil && ctx.Err() == nil { @@ -448,6 +423,45 @@ func (s *DaemonFeed) toastStreamLoop(ctx context.Context) { } } +// subscribeAndStreamEvents is one attempt of the event backoff loop: open the +// SubscribeEvents stream and fan out every SystemEvent until it errors. ctx +// cancellation stops the loop; any other error is wrapped so backoff retries. +func (s *DaemonFeed) subscribeAndStreamEvents(ctx context.Context) error { + cli, err := s.conn.Client() + if err != nil { + return fmt.Errorf("get client: %w", err) + } + stream, err := cli.SubscribeEvents(ctx, &proto.SubscribeRequest{}) + if err != nil { + return fmt.Errorf("subscribe: %w", err) + } + for { + ev, err := stream.Recv() + if err != nil { + if ctx.Err() != nil { + return ctx.Err() + } + return fmt.Errorf("stream recv: %w", err) + } + s.dispatchSystemEvent(ev) + } +} + +// dispatchSystemEvent fans one daemon SystemEvent out to the frontend +// notification stream, the typed session-warning event (when the metadata +// carries one), and the updater holder (when present). +func (s *DaemonFeed) dispatchSystemEvent(ev *proto.SystemEvent) { + se := systemEventFromProto(ev) + log.Infof("backend event: system severity=%s category=%s msg=%q", se.Severity, se.Category, se.UserMessage) + s.emitter.Emit(EventDaemonNotification, se) + if warn, ok := authsession.WarningFromMetadata(se.Metadata); ok { + s.emitter.Emit(EventSessionWarning, warn) + } + if s.updater != nil { + s.updater.OnSystemEvent(ev) + } +} + func statusFromProto(resp *proto.StatusResponse) Status { full := resp.GetFullStatus() mgmt := full.GetManagementState()