Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions hoglet.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,25 @@ func Wrap[IN, OUT any](c *Circuit, f WrappableFunc[IN, OUT]) WrappableFunc[IN, O
return out, err
}

// ensure we dedup the final - potentially wrapped - observer.
obs = dedupObservableCall(obs)

obsCtx, cancel := context.WithCancelCause(ctx)
defer cancel(errWrappedFunctionDone)

// TODO: we could skip this if we could ensure the original context has neither cancellation nor deadline
go c.observeCtx(obs, obsCtx)
// The watchdog goroutine exists to record a context cancellation/deadline as a failure promptly, even if the
// wrapped function ignores its context and blocks. If the context can never be canceled (no deadline and no
// cancellation, e.g. [context.Background]), the watchdog can never fire usefully, so we skip it and the
// associated context allocation entirely, relying solely on the deferred observation below.
//
// TODO: allow skipping the watchdog via an option for callers that guarantee their wrapped function respects
// its context, trading prompt cancellation detection for one less goroutine + context allocation per call.
if ctx.Done() != nil {
// Only here can the watchdog race the deferred observe, so dedup to ensure the - potentially wrapped -
// observer is observed exactly once. Without a watchdog the deferred func below is the sole observer
// (normal return and panic go through the same defer and are mutually exclusive), so no dedup is needed.
// This relies on breaker middleware observing synchronously; an async middleware observer must dedup itself.
obs = dedupObservableCall(obs)

obsCtx, cancel := context.WithCancelCause(ctx)
defer cancel(errWrappedFunctionDone)

go c.observeCtx(obs, obsCtx)
}

defer func() {
// ensure we also open the breaker on panics
Expand Down
Loading