Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
233 commits
Select commit Hold shift + click to select a range
e6c6cd5
refactor(server): prototype two-phase call reservations
SunSi12138 Aug 22, 2026
10d6859
test(server): cover call reservation lifecycle
SunSi12138 Aug 22, 2026
ceaab18
test(server): import threading primitives
SunSi12138 Aug 22, 2026
55dfd0d
fix(server): make call reservation ownership identity-safe
SunSi12138 Aug 22, 2026
d0f9e6b
test(server): cover stale reservation aliases
SunSi12138 Aug 22, 2026
82cf247
fix(server): harden reservation contracts for review
SunSi12138 Aug 22, 2026
8153c86
test(server): cover activation disposal transition
SunSi12138 Aug 22, 2026
6fc7d79
perf(server): add phase0 decode execution evidence runner
SunSi12138 Aug 22, 2026
f3b7952
perf(server): expose phase0 decode evidence command
SunSi12138 Aug 22, 2026
f4faaaf
ci(perf): run phase0 decode strategy matrix
SunSi12138 Aug 22, 2026
05ff549
docs(perf): document phase0 decode matrix methodology
SunSi12138 Aug 22, 2026
8a7a1a7
fix(perf): import threading primitives for decode evidence
SunSi12138 Aug 22, 2026
10b33c2
fix(perf): scope stackalloc analyzer exception to phase0 runner
SunSi12138 Aug 22, 2026
0744415
chore(perf): document relative hosted-runner evidence
SunSi12138 Aug 22, 2026
4032216
docs(perf): select adaptive decode execution model
SunSi12138 Aug 22, 2026
42664bb
perf(server): add bounded decode executor saturation evidence
SunSi12138 Aug 22, 2026
b550c72
perf(server): wire executor backpressure evidence runner
SunSi12138 Aug 22, 2026
9f288f8
perf(server): exercise bounded executor backpressure
SunSi12138 Aug 22, 2026
8db2ef6
docs(server): narrow Phase 0 decode conclusions after review
SunSi12138 Aug 22, 2026
3f7f066
fix(perf): reference runtime compression provider contract
SunSi12138 Aug 22, 2026
86e72a1
fix(perf): add IO global using for evidence runners
SunSi12138 Aug 22, 2026
dd72db2
test(perf): cover queued decode cancellation
SunSi12138 Aug 22, 2026
6936dbb
docs(perf): narrow cooperative decode conclusion
SunSi12138 Aug 22, 2026
83f5a0e
fix(perf): cancel queued persistent decode before provider
SunSi12138 Aug 22, 2026
2efbd3a
fix(perf): isolate persistent queue cancellation from A baseline
SunSi12138 Aug 22, 2026
b2a9dbc
test(bench): expose actual D cancellation seam
SunSi12138 Aug 22, 2026
5a7c84f
test(bench): probe queued cancellation through actual D
SunSi12138 Aug 22, 2026
b19eaec
fix(bench): align D probe seam accessibility
SunSi12138 Aug 22, 2026
2e7a560
docs(bench): require post-cancellation-safe-D evidence
SunSi12138 Aug 22, 2026
6428e2c
docs(bench): refresh current-D performance evidence
SunSi12138 Aug 22, 2026
317a5e5
test(perf): cover actual D blocked-writer cancellation
SunSi12138 Aug 22, 2026
00f79e3
test(perf): expose blocked-writer cancellation probe
SunSi12138 Aug 22, 2026
9d8c772
ci(perf): run actual D blocked-writer cancellation probe
SunSi12138 Aug 22, 2026
2d41c14
refactor(server): add production call permit owner for #273
SunSi12138 Aug 22, 2026
86f9297
test(server): cover production call permit lifecycle for #273
SunSi12138 Aug 22, 2026
a51ba22
test(server): align call permit fixture with transport interface
SunSi12138 Aug 22, 2026
905c003
test(server): narrow call permit nullability in assertions
SunSi12138 Aug 22, 2026
4ecc299
test(server): avoid duplicate session handshake in permit fixture
SunSi12138 Aug 22, 2026
879611d
fix(server): serialize request permit release completion
SunSi12138 Aug 23, 2026
c210381
test(server): cover concurrent permit disposal release race
SunSi12138 Aug 23, 2026
e36b2fb
test(server): keep concurrent dispose tasks non-null
SunSi12138 Aug 23, 2026
828d5c4
test(server): use dedicated disposer tasks for permit race
SunSi12138 Aug 23, 2026
223159d
refactor(runtime): add server decode resource budgets for #273
SunSi12138 Aug 23, 2026
c3222dc
refactor(server): add ResourceGovernor decode permits for #273
SunSi12138 Aug 23, 2026
d0ae9bb
refactor(server): attach decode resources to request permits for #273
SunSi12138 Aug 23, 2026
cdf34a4
refactor(server): keep decode acquisition request-owned
SunSi12138 Aug 23, 2026
d91e918
test(server): cover ResourceGovernor permit ownership for #273
SunSi12138 Aug 23, 2026
ef1ca8f
test(server): make ResourceGovernor nullable flow explicit
SunSi12138 Aug 23, 2026
56b3aa0
refactor(server): make decode permit rollback leak-safe
SunSi12138 Aug 23, 2026
ea6788d
refactor(server): preserve activation state semantics with decode per…
SunSi12138 Aug 23, 2026
2ced8af
refactor(server): keep zero-byte decode reservations state-aware
SunSi12138 Aug 23, 2026
81cbc96
refactor(server): add transferable retained-byte permits
SunSi12138 Aug 23, 2026
734a672
refactor(server): transfer retained bytes into decode permits
SunSi12138 Aug 23, 2026
c2ad656
refactor(runtime): expose decoded request owner size
SunSi12138 Aug 23, 2026
ba50f19
feat(abstractions): classify decode resource exhaustion
SunSi12138 Aug 23, 2026
47cea85
refactor(server): gate compressed admission retention by budget
SunSi12138 Aug 23, 2026
a00efe2
refactor(server): keep compressed requests cheap in reader loop
SunSi12138 Aug 23, 2026
f8ffa90
refactor(server): centralize compressed request resource gates
SunSi12138 Aug 23, 2026
7932f76
refactor(server): wire request permits before compressed decode
SunSi12138 Aug 23, 2026
e4dc10a
refactor(server): bind retained accounting to admission payload owner
SunSi12138 Aug 23, 2026
fc44a17
refactor(server): wire one-way and queued request resource ownership
SunSi12138 Aug 23, 2026
66408cf
refactor(server): align queued retention with decode ownership
SunSi12138 Aug 23, 2026
a775f99
refactor(server): preserve queued retained ownership through inline d…
SunSi12138 Aug 23, 2026
9d949e0
refactor(server): pass queued retained owner directly to dispatch
SunSi12138 Aug 23, 2026
1c3bd6a
refactor(server): remove temporary dispatch overload
SunSi12138 Aug 23, 2026
7c1d974
test(server): verify compressed decode follows call reservation
SunSi12138 Aug 23, 2026
42c98b2
test(server): fix compression capacity acceptance formatting
SunSi12138 Aug 23, 2026
b942b38
fix(server): preserve service exception mapping after request permit …
SunSi12138 Aug 23, 2026
70c5a58
test(server): pass retained owner slot to dispatch harness
SunSi12138 Aug 23, 2026
70e3a0b
test(server): cover request decode hard-budget rejection
SunSi12138 Aug 23, 2026
ff99e15
test(server): restore drain-race harness rationale
SunSi12138 Aug 23, 2026
33313ee
fix(server): create pre-decode cancellation state independently of ad…
SunSi12138 Aug 23, 2026
e977e6a
fix(server): release failed decode ownership before response backpres…
SunSi12138 Aug 23, 2026
d17629e
fix(server): release decode ownership before error response backpressure
SunSi12138 Aug 23, 2026
5e5bd60
fix(server): align one-way decode deadline ownership
SunSi12138 Aug 23, 2026
8e4e1f3
test(server): prove decode resources release before response backpres…
SunSi12138 Aug 23, 2026
5eadc0f
test(server): prove decode deadline cancellation is admission-indepen…
SunSi12138 Aug 23, 2026
8a5114f
test(server): tighten decode backpressure ownership assertions
SunSi12138 Aug 23, 2026
1994212
test(server): import cancellation primitives for decode backpressure …
SunSi12138 Aug 23, 2026
6cff14d
fix(server): transfer decoded-byte ownership with payload lifetime
SunSi12138 Aug 23, 2026
d500c93
fix(server): transfer decoded-byte permit to call state
SunSi12138 Aug 23, 2026
6b16222
fix(server): couple decoded-byte charge to payload owner
SunSi12138 Aug 23, 2026
89c3124
fix(server): transfer one-way decoded-byte ownership before teardown
SunSi12138 Aug 23, 2026
18b1fab
fix(server): transfer decoded-byte ownership before rpc teardown
SunSi12138 Aug 23, 2026
61beafd
test(server): hold decoded charge across external call-state lease
SunSi12138 Aug 23, 2026
7cc27cc
test(server): avoid touching recycled call state after lease release
SunSi12138 Aug 23, 2026
7562d8b
refactor(server): restack persistent decode executor foundation
SunSi12138 Aug 23, 2026
7832955
refactor(server): route large compressed requests through persistent …
SunSi12138 Aug 23, 2026
853ac9e
test(server): expose deterministic persistent decode starts
SunSi12138 Aug 23, 2026
10d85b2
test(server): expose persistent decode start diagnostics
SunSi12138 Aug 23, 2026
3b14628
test(server): cover persistent decode control-plane ownership
SunSi12138 Aug 23, 2026
13b2e78
fix(server): close persistent decode publication on drain
SunSi12138 Aug 23, 2026
32ddcfa
test(server): cover persistent decode graceful drain failures
SunSi12138 Aug 23, 2026
f0711e9
fix(test): expose persistent decode counter waiter
SunSi12138 Aug 23, 2026
1ce8568
fix(server): admit persistent decode before resource ownership
SunSi12138 Aug 23, 2026
0d71aaa
fix(server): satisfy persistent decode nullability
SunSi12138 Aug 23, 2026
b9985bf
test(server): cover persistent decode review invariants
SunSi12138 Aug 23, 2026
9601b58
fix(server): release decode concurrency at worker boundary
SunSi12138 Aug 23, 2026
f70d985
style: add final newline to persistent decode control-plane tests
SunSi12138 Aug 23, 2026
fd5e320
style: add final newline to persistent decode review tests
SunSi12138 Aug 23, 2026
610fddc
fix(protocol): register persistent decode queue exhaustion
SunSi12138 Aug 23, 2026
503eb17
fix(server): use registered decode queue exhaustion reason
SunSi12138 Aug 23, 2026
e44fb1a
fix(server): linearize pre-activation cancellation
SunSi12138 Aug 23, 2026
a89c5a6
fix(server): reject cancellation before call activation
SunSi12138 Aug 23, 2026
15c5cae
test(server): align graceful drain with running decode credits
SunSi12138 Aug 23, 2026
c257f32
test(server): cover persistent decode cancel before activation
SunSi12138 Aug 23, 2026
f082ae9
test(server): isolate decode queue ordering from byte budget drain
SunSi12138 Aug 23, 2026
4b6f51c
feat(server): add fair persistent decode scheduler
SunSi12138 Aug 23, 2026
a4d12ad
feat(server): schedule persistent decode by connection
SunSi12138 Aug 23, 2026
1f59df7
test(server): cover per-connection decode fairness
SunSi12138 Aug 23, 2026
b82cd2a
test(server): expose fair decode scheduler diagnostics
SunSi12138 Aug 23, 2026
8bc2096
test(server): prove persistent decode fairness across connections
SunSi12138 Aug 23, 2026
93155c5
test: include generic collections in unit globals
SunSi12138 Aug 23, 2026
d7bebc9
test(server): preserve global decode pending bound across connections
SunSi12138 Aug 23, 2026
77db7d2
fix(server): let fair decode workers exit after publication seals
SunSi12138 Aug 23, 2026
6094bdd
test(server): make real connection fairness ordering deterministic
SunSi12138 Aug 23, 2026
ab2b48d
test(server): cover fair scheduler stop lifecycle across connections
SunSi12138 Aug 23, 2026
c3991da
test(server): make fair decode routing explicitly cancellable
SunSi12138 Aug 23, 2026
df7ebe0
test(server): make fair lifecycle requests explicitly cancellable
SunSi12138 Aug 23, 2026
8308869
feat(protocol): add pre-admission stream budget exhaustion reason
SunSi12138 Aug 23, 2026
511dedc
feat(runtime): configure pre-admission stream byte budget
SunSi12138 Aug 23, 2026
aefb13f
feat(server): govern pre-admission stream bytes
SunSi12138 Aug 23, 2026
6fa8b98
refactor(runtime): bind pre-admission buffers to byte leases
SunSi12138 Aug 23, 2026
a7776a7
refactor(runtime): preserve stream-manager lease adapter
SunSi12138 Aug 23, 2026
545a829
refactor(server): expose stable stream byte callbacks
SunSi12138 Aug 23, 2026
40c572c
feat(server): budget pre-admission streams in resource governor
SunSi12138 Aug 23, 2026
50ef768
feat(server): distinguish pre-admission stream exhaustion
SunSi12138 Aug 23, 2026
bbe720d
feat(server): map stream budget exhaustion independently
SunSi12138 Aug 23, 2026
6a8c529
test(server): cover stable pre-admission stream byte budget
SunSi12138 Aug 23, 2026
f4a39ec
test(server): prove global pre-admission stream budget on wire
SunSi12138 Aug 23, 2026
282e144
test(server): cover stream budget release on force stop
SunSi12138 Aug 23, 2026
1a8407b
fix(test): correct stream budget lifecycle helper
SunSi12138 Aug 23, 2026
5215b38
style(test): normalize stream budget assertion formatting
SunSi12138 Aug 23, 2026
a3a0c51
fix(server): adapt stream budget callbacks to runtime delegates
SunSi12138 Aug 23, 2026
45efa2d
refactor(server): hand stream byte leases to runtime buffers
SunSi12138 Aug 23, 2026
60e8a33
fix(server): use compatible stream budget callback boundary
SunSi12138 Aug 23, 2026
b686cbd
test(server): avoid contextual field identifier in budget probe
SunSi12138 Aug 23, 2026
ec6d780
ci: stage integration source for exact patching
SunSi12138 Aug 23, 2026
640bd48
ci: apply deterministic integration test migration
SunSi12138 Aug 23, 2026
1e445d0
test(server): migrate stream budget overflow regression
github-actions[bot] Aug 23, 2026
bb61831
ci: restore standard PR Quick workflow
SunSi12138 Aug 23, 2026
6514f67
refactor(runtime): accept pre-admission stream byte leases directly
SunSi12138 Aug 23, 2026
ccc6c96
refactor(server): hand governor stream permits to runtime
SunSi12138 Aug 23, 2026
c0ff72a
fix(server): map pre-admission stream exhaustion terminal reason
SunSi12138 Aug 23, 2026
08f5488
test(server): expose pre-activation race hook
SunSi12138 Aug 23, 2026
35dae6a
fix(server): gate one-way activation on terminal state
SunSi12138 Aug 23, 2026
35b02f6
test(server): cover stream budget termination mapping
SunSi12138 Aug 23, 2026
9546c16
fix(server): include stable stream reason in terminal diagnostic
SunSi12138 Aug 23, 2026
605d6fd
test(server): cover stream budget pre-activation races
SunSi12138 Aug 23, 2026
42992d3
test(server): match stream exhaustion wire diagnostic
SunSi12138 Aug 23, 2026
f859008
test(server): register deterministic activation race service
SunSi12138 Aug 23, 2026
2b8082a
test(server): queue one-way calls in stream activation race
SunSi12138 Aug 23, 2026
88a2713
feat(server): add immutable admission program generations
SunSi12138 Aug 23, 2026
fcb641e
refactor(server): publish initial admission program in composition
SunSi12138 Aug 23, 2026
1950ad5
refactor(server): bind admission generation use to call lifetime
SunSi12138 Aug 23, 2026
19ad32c
test(server): add deterministic admission publication hook
SunSi12138 Aug 23, 2026
5010c19
fix(server): acquire admission generation before publication hook
SunSi12138 Aug 23, 2026
04d5694
refactor(server): capture admission program once in request loop
SunSi12138 Aug 23, 2026
1e4ac6a
refactor(server): dispatch one-way calls with captured admission gene…
SunSi12138 Aug 23, 2026
b055e9c
refactor(server): dispatch two-way calls with captured admission gene…
SunSi12138 Aug 23, 2026
de06fd7
refactor(server): retain build admission publication identity
SunSi12138 Aug 23, 2026
1787764
refactor(server): preserve controller lifecycle compatibility
SunSi12138 Aug 23, 2026
6f55323
fix(server): qualify admission publication registry type
SunSi12138 Aug 23, 2026
a3167bd
refactor(server): model disabled admission publication without reques…
SunSi12138 Aug 23, 2026
54a1bdb
refactor(server): initialize and capture admission publication once
SunSi12138 Aug 23, 2026
76b590a
test(server): cover captured admission generations and release matrix
SunSi12138 Aug 23, 2026
a2f08ba
test(server): keep retained-budget reason local to integration probe
SunSi12138 Aug 23, 2026
c44198d
chore(ci): apply scoped issue 322 harness patch
SunSi12138 Aug 23, 2026
0b6be96
chore(ci): trigger scoped issue 322 harness patch
SunSi12138 Aug 23, 2026
275366f
chore(ci): make issue 322 harness patch deterministic
SunSi12138 Aug 23, 2026
9730547
test(server): pass captured admission generation in dispatch harness
github-actions[bot] Aug 23, 2026
be9acac
chore: trigger exact-head issue 322 validation
SunSi12138 Aug 23, 2026
0a2105d
chore(ci): apply issue 322 zero-allocation ownership refinement
SunSi12138 Aug 23, 2026
7e2be17
chore: trigger admission use ownership refinement
SunSi12138 Aug 23, 2026
cd4ab9a
chore(ci): trigger issue 322 zero-allocation refinement
SunSi12138 Aug 23, 2026
48ca061
chore(ci): stage issue 322 zero-allocation patch script
SunSi12138 Aug 23, 2026
79f6e70
chore(ci): arm issue 322 ownership patch helper
SunSi12138 Aug 23, 2026
4498944
chore(ci): trigger issue 322 ownership patch helper
SunSi12138 Aug 23, 2026
ffe6155
chore(ci): correct issue 322 zero-allocation patch script
SunSi12138 Aug 23, 2026
f39649b
chore(ci): harden issue 322 zero-allocation patch matching
SunSi12138 Aug 23, 2026
8daea14
perf(server): remove admission generation use allocation
github-actions[bot] Aug 23, 2026
dcf7c9e
refactor(server): make admission use release diagnostic race-safe
SunSi12138 Aug 23, 2026
3badf2a
chore(ci): stage deterministic one-way generation test fix
SunSi12138 Aug 23, 2026
f61860c
test(server): synchronize one-way admission publication race
github-actions[bot] Aug 23, 2026
bb6f135
chore(ci): trigger deterministic one-way generation test fix
SunSi12138 Aug 23, 2026
20c46b7
test(server): synchronize one-way admission publication race
github-actions[bot] Aug 23, 2026
9a61173
chore: trigger exact-head issue 322 validation
SunSi12138 Aug 23, 2026
0cf9871
chore(ci): stage generation test barrier dedupe
SunSi12138 Aug 23, 2026
eea7771
test(server): dedupe admission publication barrier
github-actions[bot] Aug 23, 2026
20856d0
chore(ci): trigger generation test barrier dedupe
SunSi12138 Aug 23, 2026
0711faa
chore(ci): remove temporary issue 322 test helper
SunSi12138 Aug 23, 2026
1f8d0f2
refactor: add admission program retire lifecycle
SunSi12138 Aug 24, 2026
649efbb
refactor: add stable admission state kernel
SunSi12138 Aug 24, 2026
d128c22
refactor: bind admission programs to kernel state
SunSi12138 Aug 24, 2026
4ebbef7
refactor: compose stable admission lifecycle owner
SunSi12138 Aug 24, 2026
fd12f71
refactor: retire and retry admission publication capture
SunSi12138 Aug 24, 2026
a4681c0
refactor: always materialize server admission state kernel
SunSi12138 Aug 24, 2026
6601fea
test: adapt admission request owner assertions to kernel
SunSi12138 Aug 24, 2026
e0d0659
fix: close admission program registration shutdown race
SunSi12138 Aug 24, 2026
f258179
test: cover admission kernel state reuse and reclamation
SunSi12138 Aug 24, 2026
3f76126
test: keep generation regression on server-scoped kernel
SunSi12138 Aug 24, 2026
a6d6205
test: expose allocation-free admission capture probe
SunSi12138 Aug 24, 2026
dee56b3
test: cover admission capture retire and stop races
SunSi12138 Aug 24, 2026
6654ecf
fix: reclaim unreferenced admission state without unrelated traffic d…
SunSi12138 Aug 24, 2026
319cf0d
test: import threading primitives for kernel matrix
SunSi12138 Aug 24, 2026
3b4a88b
test(server): make retained-budget generation assertion deterministic
SunSi12138 Aug 24, 2026
21a3ebe
fix(server): complete admission reclamation before drain
SunSi12138 Aug 24, 2026
e893291
Add runtime admission control API
SunSi12138 Aug 24, 2026
7a3fb5c
Centralize admission publication lifecycle
SunSi12138 Aug 24, 2026
18d25c6
Test admission runtime control transactions
SunSi12138 Aug 24, 2026
29dc71f
Test runtime admission request semantics
SunSi12138 Aug 24, 2026
e78d0a1
Document runtime admission enable disable
SunSi12138 Aug 24, 2026
dfcf397
Fix runtime control test type declarations
SunSi12138 Aug 24, 2026
df5cf0f
Complete admission writer and overlap tests
SunSi12138 Aug 24, 2026
c17af5e
Add deterministic admission writer race seam
SunSi12138 Aug 24, 2026
a274a2a
Cover runtime disable stop race
SunSi12138 Aug 24, 2026
622093f
Add deterministic admission construction fault seam
SunSi12138 Aug 24, 2026
b32b847
Cover candidate rollback and stop writer race
SunSi12138 Aug 24, 2026
85cd2cc
Cover runtime admission resource regressions
SunSi12138 Aug 24, 2026
c1c6858
Clarify runtime admission stop boundary
SunSi12138 Aug 24, 2026
97bc954
fix(server): coordinate decode scheduler wake ownership
SunSi12138 Aug 24, 2026
3e7b6b4
test(server): cover stale ready wakes with four workers
SunSi12138 Aug 24, 2026
9b5a963
test(server): cover compatibility dispose publication race
SunSi12138 Aug 24, 2026
0f33f74
fix(test): make dispose race regression deterministic
SunSi12138 Aug 24, 2026
34c263a
test(server): cover four-worker connection close
SunSi12138 Aug 24, 2026
e103640
test(server): make worker saturation portable and cover remote cancel
SunSi12138 Aug 24, 2026
e803e97
chore(stack): restack #319 onto latest #312
SunSi12138 Aug 25, 2026
05593ef
chore(stack): restack #323 onto latest #319
SunSi12138 Aug 25, 2026
a5c68db
chore(stack): restack #328 onto latest #323
SunSi12138 Aug 25, 2026
1d631c6
chore(stack): restack #330 onto latest #328
SunSi12138 Aug 25, 2026
eac5c04
chore(stack): restack #330 onto merged #328
SunSi12138 Aug 26, 2026
87c97c7
test(server): align runtime admission context helpers
SunSi12138 Aug 27, 2026
a03526d
style(test): restore final newlines in runtime admission tests
SunSi12138 Aug 27, 2026
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
32 changes: 31 additions & 1 deletion doc/admission-control.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,36 @@ serverBuilder.UseAdmissionControl(options =>
});
```

## 运行时启用和停用

Server 包提供运行时控制入口,可在最初未启用接入控制的服务上原子启用,也可停用当前策略并在之后重新启用:

```csharp
ISharpLinkServer server = serverBuilder.Build();

server.EnableAdmissionControl(options =>
{
options.Global.UseConcurrency(256);
});

server.DisableAdmissionControl();

server.EnableAdmissionControl(options =>
{
options.Global.UseConcurrency(256);
});
```

`EnableAdmissionControl` 会先在发布锁之外构造、校验并解析完整候选策略;只有候选完全可用后才原子发布。回调失败、配置校验失败、生成清单解析失败或并发启用失败都不会改变当前发布状态。回调只用于构造候选配置;方法返回后继续修改调用方保留的 options 对象不会改变已发布策略。

支持的状态转换只有 Disabled → Enabled、Enabled → Disabled 和停用后的再次 Disabled → Enabled。已启用时再次调用 `EnableAdmissionControl` 不表示在线修改策略,而会抛出 `InvalidOperationException`;如需切换策略,先显式停用,再重新启用。对已停用状态重复调用 `DisableAdmissionControl` 是幂等操作。不支持这些运行时入口的自定义 `ISharpLinkServer` 实现会抛出 `NotSupportedException`。

停用只影响之后捕获接入状态的请求,不会取消已经捕获旧 generation 的活动或排队请求,也不会等待这些请求结束。旧 generation 会按正常 retire/reclaim 生命周期完成;在旧 generation 尚未回收时以兼容配置重新启用,会复用稳定 kernel 中兼容的并发、速率、队列和 partition 状态,因此不会重置已消费配额或复制全局记账。

普通的 `DisableAdmissionControl` 不是 Server Stop:它只切换 Admission publication,不触发 `StopAccepting`,也不取消或等待旧 generation。反过来,一旦 Server 已进入 Draining、Stopped 或 Faulted,Admission control plane 就已封口;之后的 `EnableAdmissionControl` 或 `DisableAdmissionControl` 都会抛出 `InvalidOperationException`,且不会再发布任何 program。与 Stop 并发时,结果按同一生命周期 writer lock 的线性化顺序决定。

运行时停用 Admission 不会停用 `ServerResourceGovernor`。调用容量、解码/预接入预算、保留字节和流式字节等服务器资源限制始终独立生效。

## 排队

只有 `MaxQueuedCalls`、`MaxQueuedBytes` 和 `MaxQueueDelay` 都允许时才等待;任何一个边界耗尽都会立即拒绝。排队仍受调用 deadline 和取消 token 约束。队列保留已解码请求字节,因此 count 与 byte 两个边界都必须配置。
Expand All @@ -60,4 +90,4 @@ Partition selector 必须同步、快速、低基数,返回稳定字符串或

permit 覆盖实际服务执行、异步 continuation 和 terminal cleanup。同步抛错、取消、响应队列失败或 Server Stop 都必须释放 permit。相关指标:active permits、queued calls、rejected calls、queue duration、active partitions。

`demo/AdmissionControl` 使用全局并发 1,证明一个调用执行时三个并发请求都收到 `ResourceExhausted`,随后已接入调用正常完成。
`demo/AdmissionControl` 使用全局并发 1,证明一个调用执行时三个并发请求都收到 `ResourceExhausted`,随后已接入调用正常完成。
12 changes: 12 additions & 0 deletions src/SharpLink.Server/Admission/AdmissionProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ internal sealed class AdmissionProgram
private const int RetiredMask = int.MinValue;
private const int UseCountMask = int.MaxValue;
private static long s_nextGenerationId;
private static Action? s_beforeProgramAttachForTests;

private readonly SharpLinkAdmissionController? _controller;
private readonly AdmissionStateKernel? _kernel;
Expand All @@ -28,6 +29,7 @@ internal AdmissionProgram(SharpLinkAdmissionController controller)
throw new InvalidOperationException("Disabled admission does not create a program generation.");
_kernel = controller.Kernel;
GenerationId = Interlocked.Increment(ref s_nextGenerationId);
Volatile.Read(ref s_beforeProgramAttachForTests)?.Invoke();
controller.AttachProgram(this);
_kernel.RegisterProgram(this);

Expand All @@ -42,6 +44,16 @@ internal AdmissionProgram(SharpLinkAdmissionController controller)

internal static AdmissionProgram Disabled { get; } = new(0);

/// <summary>
/// Deterministic candidate-construction fault seam after state bindings are acquired but before
/// the candidate attaches/registers. The kernel must release those unpublished bindings.
/// </summary>
internal static Action? BeforeProgramAttachForTests
{
get => Volatile.Read(ref s_beforeProgramAttachForTests);
set => Volatile.Write(ref s_beforeProgramAttachForTests, value);
}

internal long GenerationId { get; }

internal bool IsEnabled => _controller is not null;
Expand Down
79 changes: 75 additions & 4 deletions src/SharpLink.Server/SharpLinkServer.AdmissionProgram.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
namespace SharpLink.Server;

internal sealed partial class SharpLinkServer
internal sealed partial class SharpLinkServer : ISharpLinkAdmissionRuntimeControl
{
private static Action<SharpLinkServer, long, AdmissionProgram>? s_afterAdmissionPublicationReadForTests;
private static Action<SharpLinkServer, long, AdmissionProgram?>? s_afterAdmissionCaptureForTests;
private static Action<SharpLinkServer, AdmissionProgram>? s_afterAdmissionCandidateBuiltForTests;
private static Action<SharpLinkServer, AdmissionProgram?>? s_beforeAdmissionPublicationLockForTests;

private AdmissionProgram _admissionProgram = AdmissionProgram.Uninitialized;

Expand All @@ -23,6 +25,25 @@ internal static Action<SharpLinkServer, long, AdmissionProgram>? AfterAdmissionP
set => Volatile.Write(ref s_afterAdmissionCaptureForTests, value);
}

/// <summary>
/// Deterministic control-plane probe. It runs after a public enable candidate is fully built and
/// before the lifecycle writer lock is entered.
/// </summary>
internal static Action<SharpLinkServer, AdmissionProgram>? AfterAdmissionCandidateBuiltForTests
{
get => Volatile.Read(ref s_afterAdmissionCandidateBuiltForTests);
set => Volatile.Write(ref s_afterAdmissionCandidateBuiltForTests, value);
}

/// <summary>
/// Deterministic writer probe. A null program represents disable publication.
/// </summary>
internal static Action<SharpLinkServer, AdmissionProgram?>? BeforeAdmissionPublicationLockForTests
{
get => Volatile.Read(ref s_beforeAdmissionPublicationLockForTests);
set => Volatile.Write(ref s_beforeAdmissionPublicationLockForTests, value);
}

internal AdmissionProgram? CurrentAdmissionProgramForTests
{
get
Expand All @@ -43,6 +64,35 @@ internal AdmissionProgram CreateAdmissionProgramForTests(
Action<SharpLinkAdmissionControlOptions> configure)
{
ArgumentNullException.ThrowIfNull(configure);
return CreateAdmissionProgram(configure);
}

internal AdmissionProgram? PublishAdmissionProgramForTests(AdmissionProgram? program)
=> PublishAdmissionProgram(program, AdmissionPublicationIntent.TestReplacement);

void ISharpLinkAdmissionRuntimeControl.EnableAdmissionControl(
Action<SharpLinkAdmissionControlOptions> configure)
{
ArgumentNullException.ThrowIfNull(configure);
var candidate = CreateAdmissionProgram(configure);
try
{
Volatile.Read(ref s_afterAdmissionCandidateBuiltForTests)?.Invoke(this, candidate);
PublishAdmissionProgram(candidate, AdmissionPublicationIntent.Enable);
}
catch
{
candidate.Retire();
throw;
}
}

void ISharpLinkAdmissionRuntimeControl.DisableAdmissionControl()
=> PublishAdmissionProgram(null, AdmissionPublicationIntent.Disable);

private AdmissionProgram CreateAdmissionProgram(
Action<SharpLinkAdmissionControlOptions> configure)
{
var controller = _admissionController ??
throw new InvalidOperationException("Server admission lifecycle owner is unavailable.");
var options = new SharpLinkAdmissionControlOptions();
Expand All @@ -51,14 +101,16 @@ internal AdmissionProgram CreateAdmissionProgramForTests(
return controller.Kernel.CreateProgram(options, _staticManifests);
}

internal AdmissionProgram? PublishAdmissionProgramForTests(AdmissionProgram? program)
private AdmissionProgram? PublishAdmissionProgram(
AdmissionProgram? program,
AdmissionPublicationIntent intent)
{
var lifecycle = _admissionController ??
throw new InvalidOperationException("Server admission lifecycle owner is unavailable.");
if (program is not null && !ReferenceEquals(program.Kernel, lifecycle.Kernel))
throw new InvalidOperationException("Admission program belongs to a different server state kernel.");
if (program is { IsRetired: true })
throw new InvalidOperationException("A retired admission program cannot be published again.");

Volatile.Read(ref s_beforeAdmissionPublicationLockForTests)?.Invoke(this, program);

AdmissionProgram previous;
lock (_registryGate)
Expand All @@ -68,11 +120,23 @@ internal AdmissionProgram CreateAdmissionProgramForTests(
program?.Retire();
throw new InvalidOperationException("Admission publication is sealed because the server is stopping.");
}
if (program is { IsRetired: true })
{
throw new InvalidOperationException("A retired admission program cannot be published again.");
}

var replacement = program ?? AdmissionProgram.Disabled;
previous = ReadAdmissionPublication();
if (intent == AdmissionPublicationIntent.Enable && previous.IsEnabled)
{
program!.Retire();
throw new InvalidOperationException("Admission control is already enabled.");
}
if (intent == AdmissionPublicationIntent.Disable && !previous.IsEnabled)
return null;
if (ReferenceEquals(previous, replacement))
return previous.IsEnabled ? previous : null;

Volatile.Write(ref _admissionProgram, replacement);
if (previous.IsEnabled)
previous.Retire();
Expand Down Expand Up @@ -130,4 +194,11 @@ private AdmissionProgram ReadAdmissionPublication()
? initial
: observed;
}

private enum AdmissionPublicationIntent
{
Enable,
Disable,
TestReplacement
}
}
55 changes: 55 additions & 0 deletions src/SharpLink.Server/SharpLinkServerAdmissionControlExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
namespace SharpLink.Server;

/// <summary>Runtime admission-control operations for SharpLink servers.</summary>
public static class SharpLinkServerAdmissionControlExtensions
{
/// <summary>
/// Atomically enables admission control for requests that capture admission after this call returns.
/// </summary>
/// <param name="server">The server whose admission policy is enabled.</param>
/// <param name="configure">Builds the complete admission policy before publication.</param>
/// <exception cref="ArgumentNullException"><paramref name="server"/> or <paramref name="configure"/> is null.</exception>
/// <exception cref="InvalidOperationException">Admission is already enabled, or the server is stopping.</exception>
/// <exception cref="NotSupportedException">The server implementation does not support runtime admission control.</exception>
public static void EnableAdmissionControl(
this ISharpLinkServer server,
Action<SharpLinkAdmissionControlOptions> configure)
{
ArgumentNullException.ThrowIfNull(server);
ArgumentNullException.ThrowIfNull(configure);
if (server is not ISharpLinkAdmissionRuntimeControl runtimeControl)
{
throw new NotSupportedException(
"This ISharpLinkServer implementation does not support runtime admission control.");
}

runtimeControl.EnableAdmissionControl(configure);
}

/// <summary>
/// Atomically disables admission control for requests that capture admission after this call returns.
/// Requests that already captured an enabled generation retain it until terminal completion.
/// </summary>
/// <param name="server">The server whose admission policy is disabled.</param>
/// <exception cref="ArgumentNullException"><paramref name="server"/> is null.</exception>
/// <exception cref="InvalidOperationException">The server is stopping.</exception>
/// <exception cref="NotSupportedException">The server implementation does not support runtime admission control.</exception>
public static void DisableAdmissionControl(this ISharpLinkServer server)
{
ArgumentNullException.ThrowIfNull(server);
if (server is not ISharpLinkAdmissionRuntimeControl runtimeControl)
{
throw new NotSupportedException(
"This ISharpLinkServer implementation does not support runtime admission control.");
}

runtimeControl.DisableAdmissionControl();
}
}

internal interface ISharpLinkAdmissionRuntimeControl
{
void EnableAdmissionControl(Action<SharpLinkAdmissionControlOptions> configure);

void DisableAdmissionControl();
}
Loading