-
Notifications
You must be signed in to change notification settings - Fork 1
Timeout
Marco Breveglieri edited this page Jul 20, 2026
·
1 revision
The Timeout pattern aborts an operation that takes too long, so a hung dependency cannot hang your application.
- Calls to network services that may hang indefinitely
- Third-party APIs without their own reliable timeout
- Enforcing an SLA on how long an operation is allowed to take
- Protecting the UI thread from a slow background call
- Operations that already have a robust timeout of their own (e.g. an HTTP client with a configured timeout lower than yours)
- Non-idempotent operations that cannot be safely abandoned mid-flight (the underlying task keeps running in the background even after the timeout fires)
- As a substitute for cancellation support in the called API - Timeout abandons the wait, it does not stop the work
uses Murphy.Policy.Timeout;
var
Policy: ITimeoutPolicy;
begin
Policy := TTimeoutBuilder
.Handle([])
.After(TTimeSpan.FromSeconds(5))
.Build;
Policy.Execute(procedure begin CallSlowService; end);
end;procedure FetchWithDeadline;
var
Policy: ITimeoutPolicy;
begin
Policy := TTimeoutBuilder
.Handle([])
.After(TTimeSpan.FromSeconds(3))
.Build;
Policy.Execute(
procedure
begin
HTTP.Get('https://api.example.com/data');
end);
end;var Policy: ITimeoutPolicy;
begin
Policy := TTimeoutBuilder
.Handle([])
.After(TTimeSpan.FromSeconds(5))
.OnTimeout(procedure(Context: TTimeoutContext)
begin
WriteLn(Format('Timed out after %s (limit was %s)',
[Context.ElapsedTime.ToString, Context.TimeoutDuration.ToString]));
end)
.Build;
Policy.Execute(procedure begin CallSlowService; end);
end;var Policy: ITimeoutPolicy;
begin
Policy := TTimeoutBuilder.Handle([]).After(TTimeSpan.FromSeconds(2)).Build;
try
Policy.Execute(procedure begin CallSlowService; end);
except
on E: ETimeoutRejectedException do
WriteLn('Operation aborted: took too long');
end;
end;Retry the operation with a fresh timeout budget on each attempt:
uses Murphy.Policy.Retry, Murphy.Policy.Timeout, Murphy.Policy.Wrap;
var Policy: IPolicyWrap;
begin
Policy := TPolicyWrapBuilder.Wrap([
TRetryBuilder.Handle(ETimeoutRejectedException).Retry(3),
TTimeoutBuilder.Handle([]).After(TTimeSpan.FromSeconds(2))
]);
Policy.Execute(procedure begin CallSlowService; end);
end;- Pick a duration tied to a real requirement - a UI budget, an SLA, or an upstream deadline
- Remember losing work keeps running - the abandoned task is not cancelled, only its result is ignored; only use Timeout on operations safe to abandon
-
Use
OnTimeoutfor observability - log elapsed time to tune the threshold over time - Combine with Retry - retry a timed-out attempt rather than giving up immediately
-
Note that
Handle()is ignored - the timeout fires regardless of exception type; any exception types passed are not used by this pattern