Repository navigation
[Runtime Configuration][Client] Dynamic global request-timeout policy #578
Description
Parent tracker: #262
Related lifetime/deadline foundation: #287
Goal
Allow one running ISharpLinkClient instance to update its client-wide default request-timeout fallback without rebuilding or replacing the Client.
This is intentionally a narrow next-logical-call policy. It does not make method metadata, caller cancellation, connection/handshake timeouts, or session limits dynamically mutable.
Runtime semantics
Support a client-wide timeout policy with three states:
Recommended/default timeout
Custom timeout
Disabled
An update affects only logical RPCs that start after publication:
Call A starts under timeout generation N
runtime update publishes generation N+1
Call A keeps its already-resolved deadline
Call B starts under generation N+1
The existing method timeout precedence remains unchanged:
explicit method [Timeout(value)]
> client-wide fallback
parameterless method timeout policy
may use the client-wide fallback according to current semantics
A runtime update must not rewrite an already-created RpcDeadline or extend/shorten an in-flight logical call.
Scope
- runtime enable/set of the client-wide default timeout;
- runtime disable of the client-wide default timeout;
- update to a new positive timeout value;
- full candidate validation before publication;
- atomic publication with next-logical-call visibility;
- in-flight call generation consistency;
- update vs Stop/Dispose race semantics;
- no new per-call allocation or request-path lock;
- diagnostics/docs expose the effective current client-wide timeout policy where appropriate.
Explicitly out of scope
- dynamic mutation of method
[Timeout]metadata; - caller
CancellationTokenor per-call options; - per-attempt timeout;
- connect/handshake/readiness timeout;
- heartbeat/lifecycle timeout;
- server-side timeout policy;
- retry policy implementation (tracked separately under [Runtime Configuration] 动态配置 / Hot Reload 长期跟踪 #262);
- active-call deadline renegotiation.
Correctness invariants
- A logical call resolves the effective timeout/deadline once at its invocation boundary.
- Runtime update cannot alter an already-resolved
RpcDeadline. - Invalid updates are rejected before publication and leave the current policy unchanged.
- Disabled timeout means no client-wide fallback; existing method/inherited/caller lifetime semantics remain authoritative.
- DeadlineExceeded remains the terminal outcome once the logical-call deadline wins.
- Stop/Dispose prevents or deterministically rejects further policy publication according to the established dynamic-config lifecycle pattern.
- No request-path global lock, timer-per-policy, or per-call policy allocation is introduced.
Validation
At minimum cover:
- enabled -> new duration;
- enabled -> disabled;
- disabled -> enabled;
- invalid duration rollback;
- update while an old call is in flight;
- update immediately before/after a new call starts;
- method timeout precedence;
- inherited time budget behavior;
- caller cancellation remains independent;
- concurrent repeated updates;
- update vs Stop/Dispose;
- tiny unary hot-path allocation/performance before/after.
Completion
This issue is complete when a running Client can atomically replace only its global request-timeout fallback, with existing calls retaining their captured deadline and new calls observing the new policy.
Activity
SunSi12138 commentedon Sep 7, 2026
Implemented and reviewed in #593, now squash-merged into
devasd03ef7ed0ab3f9171178f8fde0c2b36ba1b6efd5. Runtime request-timeout updates preserve per-logical-call generation semantics, lifecycle rejection, and the no-lock hot path; PR Fast, Extended, and CodeQL are green. Closing as completed.