From 4f2c57ac402cb3aa8e132dbb76b6b7b9126a6bdc Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Tue, 28 Apr 2026 06:21:08 -0500 Subject: [PATCH] pkg/services: add Engine.GoTickUntil & Engine.WaitFor --- pkg/services/service.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/pkg/services/service.go b/pkg/services/service.go index 6257ff6b51..3038ac88ec 100644 --- a/pkg/services/service.go +++ b/pkg/services/service.go @@ -107,6 +107,36 @@ func (e *Engine) GoTick(ticker *timeutil.Ticker, fn func(context.Context)) { }) } +// GoTickUntil is like GoTick but halts when fn returns true, and closes the returned chan. +func (e *Engine) GoTickUntil(ticker *timeutil.Ticker, fn func(context.Context) bool) <-chan struct{} { + ch := make(chan struct{}) + e.Go(func(ctx context.Context) { + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + if fn(ctx) { + close(ch) + return + } + } + } + }) + return ch +} + +// WaitFor blocks on receiving from ch then return true, or exits early if the Engine is closed and returns false. +func (e *Engine) WaitFor(ch <-chan struct{}) bool { + select { + case <-e.StopChan: + return false + case <-ch: + } + return true +} + // Tracer returns the otel tracer with service attributes included. func (e *Engine) Tracer() trace.Tracer { return e.tracer