Skip to content

[Runtime Configuration][Client] Dynamic endpoint admission policy replacement #582

Closed

Description

@SunSi12138

Parent tracker: #262

Goal

Allow a running ISharpLinkClient to dynamically enable, replace, or disable a custom ISharpLinkEndpointAdmissionPolicy without rebuilding the Client.

This issue is intentionally narrow. SharpLink treats the custom policy as an application-owned black-box SPI and does not attempt to understand or migrate its internal state.

Runtime semantics

Supported modes:

Disabled
Custom(policy)

Supported transitions:

Disabled -> Custom A
Custom A -> Custom B
Custom A -> Disabled

The publication boundary is next endpoint attempt, not next logical call.

For every successfully acquired attempt:

Attempt captures Policy A
Policy A.TryAcquire(...) returns token A
runtime update publishes Policy B
attempt completes
Policy A.Report(outcome, token A)

A later attempt may capture Policy B.

TryAcquire and Report for one admitted attempt must always bind to the same captured policy instance/generation.

Scope

  • runtime enable of a custom endpoint admission policy;
  • runtime replacement of one custom policy with another;
  • runtime disable;
  • atomic publication for future attempts;
  • capture the exact policy used by TryAcquire and retain it until the attempt terminal report;
  • preserve the existing opaque policy-owned token unchanged;
  • old admitted attempts continue to report to their captured old policy after replacement/disable;
  • rejected attempts do not create a report lease;
  • invalid/null publication is rejected without changing the current policy;
  • update vs Stop/Dispose is deterministic;
  • no request-path global lock;
  • disabled healthy path retains the existing fast path and does not add per-attempt allocation solely for dynamic configuration;
  • custom admission remains mutually exclusive with the built-in Circuit Breaker mode.

Explicitly out of scope

  • custom policy option/configuration mutation by SharpLink;
  • migration, cloning, serialization, reset, or reconciliation of application-owned policy state;
  • per-endpoint dynamic configuration APIs;
  • per-method dynamic configuration APIs;
  • policy chaining/composition;
  • asynchronous admission policies;
  • changing the ISharpLinkEndpointAdmissionPolicy decision/outcome contract;
  • Circuit Breaker parameter/state semantics (tracked separately under [Runtime Configuration] 动态配置 / Hot Reload 长期跟踪 #262);
  • topology/load-balancing redesign.

Applications that need fine-grained dynamic rules inside one custom policy may keep the same policy object and implement their own immutable configuration snapshot internally; SharpLink does not manage that internal control plane.

Correctness invariants

  1. One admitted endpoint attempt owns exactly one captured admission policy reference and one opaque token.
  2. The policy that grants an attempt is the only policy that receives its terminal Report.
  3. Replacing or disabling the current policy cannot redirect an old attempt's terminal report to a newer policy.
  4. Old policy instances remain strongly reachable only while outstanding admitted attempts still need to report to them; SharpLink must not retain retired policies indefinitely after drain.
  5. Report exceptions remain isolated according to the existing contract and cannot corrupt pending-call terminal ownership.
  6. No second attempt completion state machine or pending registry is introduced.

Validation

At minimum cover:

  • disabled -> custom;
  • custom A -> custom B;
  • custom -> disabled;
  • update between TryAcquire and attempt terminal completion;
  • update while a retrying logical call is between attempts: old attempt reports to old policy, next attempt may use new policy;
  • rejected attempt around publication boundary;
  • policy TryAcquire throw;
  • policy Report throw;
  • caller cancellation/deadline/connection-close/GoAway/send-failure terminal outcomes;
  • concurrent repeated replacements;
  • update vs Stop/Dispose;
  • retired policy released after outstanding reports drain;
  • healthy admission-disabled allocation/performance gate.

Completion

This issue is complete when custom endpoint admission can be atomically enabled/replaced/disabled for future attempts while every outstanding admitted attempt remains permanently paired with the exact policy/token generation that admitted it.

Activity

  1. SunSi12138 commented on Sep 8, 2026

    @SunSi12138
    OwnerAuthor

    Implemented and reviewed in #596, now squash-merged into dev as 8f40d8fa84dadddb52d301a15881a6c9123e83ab. The runtime endpoint-admission publication keeps the request path lock-free, binds each admitted attempt to the exact policy/token that granted it, re-evaluates admission at retry-attempt boundaries, preserves custom/circuit-breaker mutual exclusion, and rejects publication after shutdown begins. Final PR Fast rerun, PR Extended, CodeQL, and pending/codec validation are green. Closing as completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions