docs(route): define TURN allocation admission truth (#207)
* docs(route): define TURN allocation admission * docs(route): align TURN admission source truth
This commit is contained in:
1 parent
ba623c67e6
commit
c30f4e9f73
9 files changed
+76
-22
No files matched your search
@@ -184,6 +184,16 @@ SFU and TURN remain bounded fallback resources with independent deployment-wide
|
||||
admission. Resource exhaustion produces the next bounded candidate, an explicit
|
||||
wait, or failure; it never creates unbounded central fanout.
|
||||
|
||||
For the single-process deployment, selected TURN uses one injected allocation
|
||||
authority with an explicitly configured positive safe-integer capacity and no
|
||||
product default. Each exact `peer-selected` transport and Host-SFU ingress
|
||||
transport consumes one unit. The controller reserves that unit before issuing a
|
||||
credential, commits only the matching current identity, and keeps reserved,
|
||||
committed, and draining entries charged until their logical authorization is
|
||||
released. Independent logical edges may coexist up to this deployment capacity;
|
||||
the capacity is not derived from endpoint media-copy capacity, Viewer admission,
|
||||
or a room-wide lease count.
|
||||
|
||||
For the single-process deployment, SFU admission is one injected authority with
|
||||
deployment-wide ingress and egress counters. Enabling LiveKit requires explicit
|
||||
positive safe-integer `SFU_INGRESS_CAPACITY` and `SFU_EGRESS_CAPACITY` values;
|
||||
|
||||
+32
-11
@@ -228,15 +228,35 @@ SFU_INGRESS_CAPACITY=<MEASURED_DEPLOYMENT_INGRESS_COPIES>
|
||||
SFU_EGRESS_CAPACITY=<MEASURED_DEPLOYMENT_EGRESS_COPIES>
|
||||
```
|
||||
|
||||
To enable exact selected TURN after bounded peer and SFU recovery, add its
|
||||
complete tuple:
|
||||
|
||||
```dotenv
|
||||
SELECTED_EDGE_TURN_URLS=turn:turn.example.com:3478?transport=udp
|
||||
SELECTED_EDGE_TURN_SHARED_SECRET=<INDEPENDENT_SECRET_OF_AT_LEAST_32_BYTES>
|
||||
SELECTED_EDGE_TURN_CREDENTIAL_TTL_SECONDS=120
|
||||
SELECTED_EDGE_TURN_ALLOCATION_CAPACITY=<MEASURED_DEPLOYMENT_ALLOCATIONS>
|
||||
```
|
||||
|
||||
The rejected `PEER_ICE_TURN_*` participant-wide tuple is removed; supplying any
|
||||
stale key, even blank, fails startup. The deployed source uses the complete
|
||||
`SELECTED_EDGE_TURN_URLS`, `SELECTED_EDGE_TURN_SHARED_SECRET`, and
|
||||
`SELECTED_EDGE_TURN_CREDENTIAL_TTL_SECONDS` tuple with one explicit TURN/UDP URI,
|
||||
an independent secret and bounded TTL. The current production tuple uses the
|
||||
coturn UDP endpoint and a 120-second TTL; only the controller-selected edge may
|
||||
receive a short-lived grant. Roll back by removing the application tuple before
|
||||
changing coturn or firewall state. Credentials never enter URLs, logs, browser
|
||||
persistence, room rows, or SQLite.
|
||||
stale key, even blank, fails startup. Current source requires the complete
|
||||
four-value `SELECTED_EDGE_TURN_*` tuple with one explicit TURN/UDP URI, an
|
||||
independent secret, bounded TTL, and positive safe-integer logical-allocation
|
||||
capacity. Each exact peer-selected edge and Host-SFU ingress consumes one unit
|
||||
from the same process ledger before credential issuance; reserved, committed,
|
||||
and draining authorizations stay charged until exact logical release. The
|
||||
production release remains on its recorded configuration until the four-value
|
||||
tuple is supplied atomically with current source. Only a controller-selected
|
||||
edge may receive a short-lived grant. Roll back by
|
||||
removing the application tuple before changing coturn or firewall state.
|
||||
Credentials never enter URLs, logs, browser persistence, room rows, or SQLite.
|
||||
|
||||
Application release does not prove deletion of the matching physical coturn
|
||||
allocation. Keep the credential TTL short and configure coturn `user-quota` and
|
||||
`total-quota` to bound allocations left by disconnect or process restart. A
|
||||
restarted single process begins a fresh logical ledger while old physical
|
||||
allocations expire under those coturn bounds; do not claim cross-restart
|
||||
reconstruction or per-allocation readback.
|
||||
|
||||
Before a media canary, `npm run gate:turn-udp-allocation` provides the bounded
|
||||
UDP allocation check. It proves only that an authenticated relay candidate can
|
||||
@@ -277,10 +297,11 @@ A peer child or the Host's single SFU publication consumes one copy, upstream
|
||||
receive is free, a committed selected TURN transport for the same child does not
|
||||
consume a second copy, and an uncommitted selected carry does. Transition work
|
||||
may reach only `min(C + 1, 3)`. A Host already sending three copies at `C=3`
|
||||
must fail or wait before a fourth publication token or TURN grant is issued.
|
||||
must fail or wait before a fourth endpoint copy is issued; changing an existing
|
||||
copy to selected TURN remains the same endpoint copy and separately requires
|
||||
TURN allocation admission.
|
||||
Supplying the removed `MAX_PEER_RELAY_DOWNSTREAM_EDGES`, even blank, fails
|
||||
startup. The room-wide selected-lease guard remains a temporary server safety
|
||||
boundary until per-edge TURN allocation admission replaces it.
|
||||
startup.
|
||||
|
||||
Production release `9461e20` still runs the legacy Host-2/Browser-1 policy on
|
||||
wire `screener-v5`. Deploy the current source server, Web assets, and Native
|
||||
|
||||
@@ -22,7 +22,7 @@ Last updated: 2026-08-23
|
||||
## Current Source And Production
|
||||
|
||||
- Canonical source is the clean `main` branch. New branches and worktrees start from its exact current commit after accepted truth is merged.
|
||||
- Current source implements the uniform `1/2/3` endpoint cap through one shared accounting guard, advances Web/server/Native to `screener-v6`, rejects v5 before room authority, and carries the exact deployment cap in every authenticated snapshot so ordinary Host authorization, Native admission, peer-assisted assignments, and sender slots use the same authority. SFU-fed Viewers remain leaves without outbound proof. SFU admission uses explicit no-default ingress/egress capacities, exact `reserved | committed | draining` lifecycle accounting, and a listener-fenced dedicated LiveKit owner; the room-wide selected-lease guard remains for its independent TURN-admission wave.
|
||||
- Current source implements the uniform `1/2/3` endpoint cap through one shared accounting guard, advances Web/server/Native to `screener-v6`, rejects v5 before room authority, and carries the exact deployment cap in every authenticated snapshot so ordinary Host authorization, Native admission, peer-assisted assignments, and sender slots use the same authority. SFU-fed Viewers remain leaves without outbound proof. SFU admission uses explicit no-default ingress/egress capacities, exact `reserved | committed | draining` lifecycle accounting, and a listener-fenced dedicated LiveKit owner. Selected TURN uses its own explicit no-default deployment capacity and exact logical-allocation ledger shared by independent peer edges and Host-SFU ingress.
|
||||
- Production runs exact `9461e207af62b4f38f6b7a8aa16f8beb49e0e4ee`, release `9461e20`, wire `screener-v5`; `21d5cd9f7139` is the rollback release.
|
||||
- Production still enforces Host downstream `2`, ordinary Browser downstream `1`, deployment values `1/2`, a fixed SFU-root limit of `2`, and legacy publication/selected accounting. This is a dated implementation divergence, not current product policy.
|
||||
- Production has automatic routing, bad-relay corroboration, peer-quality make-before-break with Viewer and Host provisional parents, selected-edge transport, stable route/connection details, 64/128/256 audio choices, access controls, self-check, diagnostic export, and signaling watchdog behavior.
|
||||
@@ -32,7 +32,7 @@ Last updated: 2026-08-23
|
||||
## Current Priority
|
||||
|
||||
1. Keep this truth set and [the TODO ledger](./todo.md) concise and internally consistent.
|
||||
2. Complete and release route waves C-D first. Then release live audio and paused video-codec switching, follow with evidence-led H.264 diagnosis, the strict-NAT emulator gate, connection feedback, and the remaining functional roadmap. Distribution packaging starts only after those TODOs are complete. Parallel branches may finish earlier but do not change this merge/deployment order.
|
||||
2. Complete and release the remaining route-controller convergence first. Then release live audio and paused video-codec switching, follow with evidence-led H.264 diagnosis, the strict-NAT emulator gate, connection feedback, and the remaining functional roadmap. Distribution packaging starts only after those TODOs are complete. Parallel branches may finish earlier but do not change this merge/deployment order.
|
||||
|
||||
## Working Rules
|
||||
|
||||
|
||||
@@ -588,6 +588,27 @@ example benchmark cannot supply Screener defaults. A later multi-process
|
||||
Screener deployment needs a shared atomic ledger; independent process-local
|
||||
counters would not be deployment-wide admission.
|
||||
|
||||
## Deployment-Wide TURN Admission
|
||||
|
||||
Selected TURN needs its own deployment admission because coturn REST credentials
|
||||
authenticate a bounded bearer but do not enforce Screener's room, edge, session,
|
||||
revision, or connection identity. The current single-process boundary is one
|
||||
O(1) logical-allocation ledger with an explicit positive safe-integer capacity
|
||||
and no default. Each exact `peer-selected` transport and Host-SFU ingress
|
||||
transport reserves one unit before credential issuance; reserved, committed, and
|
||||
draining authorizations remain charged until the application releases that exact
|
||||
identity. Independent edges may therefore coexist without a room-wide lease
|
||||
rule, while exhaustion returns to the existing bounded fallback path.
|
||||
|
||||
Coturn exposes no application control-plane operation that deletes and reads
|
||||
back one exact Screener allocation. The logical ledger therefore does not claim
|
||||
physical allocation drain proof. Short credential TTL plus coturn `user-quota`
|
||||
and `total-quota` bound allocations that outlive a logical authorization or an
|
||||
application restart. A restarted single process starts a new logical owner and
|
||||
cannot reconstruct the old in-memory ledger; a multi-process or stronger
|
||||
cross-restart claim would require a shared atomic owner or a coturn control
|
||||
contract and is outside this wave.
|
||||
|
||||
## Route Screening
|
||||
|
||||
| Route | Where copies are emitted | Endpoint cost | Evidence status |
|
||||
|
||||
+3
-3
@@ -16,15 +16,15 @@ This is the current execution index. Git history owns completed timelines; [veri
|
||||
- Canonical source is the clean `main` branch; auxiliary branches and worktrees do not own current truth.
|
||||
- Current source implements one steady outbound media-copy cap for every non-server endpoint: default `2`, static `1/2/3`, a peer child or Host publication consumes one slot, upstream receive is free, a committed selected TURN transport replaces the same copy while hidden carry consumes another, and no Browser/UA/visibility tier exists. One shared guard owns the accounting and transition work is bounded by `min(C + 1, 3)`.
|
||||
- The v6 release boundary rejects v5 before room authority and carries the exact deployment cap in every authenticated snapshot so ordinary Host authorization, Native admission, peer-assisted child assignments, and sender slots share the server authority. It leaves an SFU-fed Viewer childless without independent outbound proof and keeps quality events child-scoped without a fixed two-child parent drain.
|
||||
- Current source also implements explicit no-default SFU ingress/egress capacities and exact `reserved | committed | draining` accounting. The listener owner reconciles its dedicated non-auto-create LiveKit namespace before serving, creates each generation before token issuance, releases only after delete-plus-absence proof, and reclaims Host-offline generations through bounded exact-participant checks. The room-wide selected-lease guard remains until its separate TURN-admission wave.
|
||||
- Current source also implements explicit no-default SFU ingress/egress capacities and exact `reserved | committed | draining` accounting. The listener owner reconciles its dedicated non-auto-create LiveKit namespace before serving, creates each generation before token issuance, releases only after delete-plus-absence proof, and reclaims Host-offline generations through bounded exact-participant checks. Selected TURN has an independent explicit no-default deployment capacity; one process-local ledger charges every exact peer-selected edge and Host-SFU ingress through reserve, commit, drain, and release.
|
||||
- Automatic P2P-first routing, one active upstream, an acyclic graph, exact identity/generation authority, media-proven make-before-break, and bounded failure remain accepted.
|
||||
- The holistic assisted-route model is accepted: one controller performs allocation, child reparenting, and relay abdication/drain. One Host publication serves SFU subscriptions; TURN is an exact edge transport, not a topology node. Endpoint accounting, the wire boundary, and SFU admission/lifecycle are implemented; independent TURN admission and controller convergence remain pending.
|
||||
- The holistic assisted-route model is accepted: one controller performs allocation, child reparenting, and relay abdication/drain. One Host publication serves SFU subscriptions; TURN is an exact edge transport, not a topology node. Endpoint accounting, the wire boundary, SFU lifecycle, and TURN admission are implemented; controller convergence remains pending.
|
||||
- Parent selection is deterministic rather than random or score-based: hard eligibility filters, then shallowest result, remaining sender capacity, stable join order, and peer identity; one provisional edge uses standard ICE and media proof at a time. Viewer connection feedback and the strict-NAT emulator gate are accepted follow-up work, not deployed behavior.
|
||||
- Live 64/128/256 audio-ceiling mutation and paused-share video codec switching are accepted but not yet implemented on canonical `main`. H.264 startup blur/low-FPS reports remain an evidence-led diagnosis, not a presumed codec defect. Public-server and fully local distribution packages are later work after the functional, NAT, and real-network ledger is complete.
|
||||
|
||||
## Current Milestone
|
||||
|
||||
1. Complete and release route waves C-D with independent TURN admission, deterministic local parent selection, quality ownership, and one controller.
|
||||
1. Complete and release the remaining route-controller convergence with deterministic local parent selection and quality ownership.
|
||||
2. Release live audio-ceiling mutation and paused-share codec switching on the resulting generation/transition boundary.
|
||||
3. Reproduce the H.264 startup report before any codec-specific repair, and build the strict-NAT emulator gate before any manually approved canary in an operator-owned test room.
|
||||
4. Add first-frame-driven Viewer connection stages and finish the remaining accepted functional and real-network work.
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ Only items in **Now** are executable after their stated decision gate. A branch
|
||||
|
||||
## Now
|
||||
|
||||
1. **Route Waves C-D: TURN admission, selection, and controller convergence.** Replace the remaining room-wide selected-lease guard with per-edge TURN allocation admission and exact accounting. Converge allocation, child reparent, and relay drain on one committed graph/controller. A signaling-connected relay that stops current-generation RTP cannot require its own report: after the bounded parent-proof deadline, persistent child-side silence reparents only the affected child whether the parent proved sending or not; cordon or drain the relay only after parent/session hard failure, explicit sender/resource failure, failed ingress repair, or independent downstream evidence. Parent candidates use hard eligibility filters followed by deterministic shallowest, remaining-capacity, join-order, and peer-identity ordering; standard ICE plus exact media proof tests one candidate at a time. Do not add raw-IP/NAT ranking, all-pairs probes, a weighted score, UA/visibility tiers, or periodic rebalancing. The remaining temporary guard is a safety boundary, not accepted product policy, and must not be removed early.
|
||||
1. **Route Wave D: controller convergence.** Converge allocation, child reparent, and relay drain on one committed graph/controller. A signaling-connected relay that stops current-generation RTP cannot require its own report: after the bounded parent-proof deadline, persistent child-side silence reparents only the affected child whether the parent proved sending or not; cordon or drain the relay only after parent/session hard failure, explicit sender/resource failure, failed ingress repair, or independent downstream evidence. Parent candidates use hard eligibility filters followed by deterministic shallowest, remaining-capacity, join-order, and peer-identity ordering; standard ICE plus exact media proof tests one candidate at a time. Do not add raw-IP/NAT ranking, all-pairs probes, a weighted score, UA/visibility tiers, or periodic rebalancing.
|
||||
2. **Switch screen-audio ceilings live.** Keep Opus fixed and serialize 64/128/256 kbps desired profile updates across every current Host, relay, and SFU audio sender. Each endpoint uses fresh `getParameters()`/`setParameters()` readback, ignores stale completions, retains media plus its prior applied value on failure, and applies the latest desired value to future edges. Do not add a remote applied-ack protocol or claim room-wide atomic convergence in this slice.
|
||||
3. **Switch video codec while paused.** After the route/media-generation boundary is available, serialize the change with route mutation, freeze exact current route/media bindings, hold new joins, renegotiate P2P/relay and republish SFU while paused, then verify actual codec plus decoded frames on resume. A binding invalidated by leave or hard route failure exits this proof set and waits for routing to rebuild from the final committed preference after the bounded codec transaction settles. On failure pause again and perform bounded rollback; rollback proves the prior preference was reapplied plus a newly negotiated actual codec and decoded progress, not literal equality with the old actual codec. Zero targets update only the future-edge preference. Reset `automatic` with empty codec preferences. This is a paused bounded-gap transaction; unpaused make-before-break is a later extension.
|
||||
4. **Diagnose the production H.264/blur report.** Reproduce exact release `769de201f7cc` against current `main` on the same Host/browser/driver/game and one wired direct Viewer, changing one variable at a time. Implement a codec-specific repair only if codec/encoder evidence identifies it; otherwise fix the proven capture, sender, BWE, or lifecycle cause.
|
||||
|
||||
@@ -12,7 +12,7 @@ Capacity and routing entries below describe the exact tested source or release o
|
||||
|
||||
- Production runs exact `9461e207af62b4f38f6b7a8aa16f8beb49e0e4ee`, release `9461e20`, with `21d5cd9f7139` retained for rollback.
|
||||
- Local/public health return 200; `screener`, LiveKit, coturn, and nginx are active; `screener` reports zero restarts. SQLite v3 has five rooms, SHA-256 `aef724ae52c4107be8ec8791e72f8dcaa11b0ec849fb432d022e2cfb9cfe0974`, owner `screener:screener`, and mode 0600.
|
||||
- Room admission defaults to eight and accepts explicit limits from one through sixteen. In the exact release, the unset endpoint-cap environment yielded Host2/ordinary Browser Viewer1, active/provisional/selected overlays were charged, SFU roots were limited to two, and one `peer-selected` lease was allowed per room excluding Host ingress. Those are release facts only. The accepted target is steady endpoint cap `2` with static `1/2/3`, Host-publication slot accounting, same-edge TURN transport, and independent bounded server admission.
|
||||
- Room admission defaults to eight and accepts explicit limits from one through sixteen. In the exact release, the unset endpoint-cap environment yielded Host2/ordinary Browser Viewer1, active/provisional/selected overlays were charged, SFU roots were limited to two, and one `peer-selected` lease was allowed per room excluding Host ingress. Those are release facts only. Current source uses steady endpoint cap `2` with static `1/2/3`, Host-publication slot accounting, same-edge TURN transport, and independent bounded server admission.
|
||||
- The deployed SFU path enforces the release's controller/token root cap, Host-publication edge accounting, zero-child assignment/subscriber retention, and `dynacast: false`. The tagged local gate covers those release invariants; the accepted route migration still requires real shaped LiveKit packet flow, BWE downshift/recovery, resource, and root-with-children validation.
|
||||
- Share audio presets and local-only Host SFU, codec/encoder, A/V, and selected-candidate diagnostics are deployed. Their target-browser field availability and actual media values remain unverified.
|
||||
- The bounded pre-share self-check, privacy-safe local JSON export, signaling-partition recovery, and peer-quality MBB are deployed. An ordinary Viewer with a peer/SFU upstream or the Host may own a separately budgeted provisional child; sibling MBB remains open. Real-route behavior remains part of the routing gate.
|
||||
@@ -22,6 +22,7 @@ Capacity and routing entries below describe the exact tested source or release o
|
||||
|
||||
- Exact source `31e323e2754fcfde15f7b4d69e925ec71e2795cb` passed repository hygiene, TypeScript typecheck, client/server builds, all 660 Web tests, all Native Go packages, `go vet`, and two independent P0/P1 reviews. The tests cover strict v6 endpoint-cap authentication, ordinary active/waiting authorization and grace promotion, Native cap propagation and admission, and peer-assisted cap rejection. This is local state-machine/build evidence, not a complete Native physical-slot matrix or production, browser-quality, or heterogeneous-network acceptance.
|
||||
- Exact Wave B implementation source `815c6174d411c55648daf5cd6ac4c42f64effff9`, based on `d1ba2e52919225e67ad0c8dd2b660f333fbc88fd`, passed its 372-test SFU-admission gate, all 690 Web tests, TypeScript typecheck, and client/server builds. Focused tests cover reserved/committed/draining accounting, reserve-before-token enforcement, explicit room lifecycle, listener-owner startup fencing, restart cleanup, stale-token replay boundaries, Host-offline reclamation, shutdown races, and two-room global admission. This is fake-control-plane and local state-machine evidence, not a real LiveKit process/JWT replay, packet-flow, multi-process, deployment-capacity, or production proof.
|
||||
- Current source TURN-admission unit and signaling tests cover independent peer and Host-SFU logical edges, shared capacity exhaustion, exact reserve/commit/drain/release identity, current-share cleanup, and graceful shutdown. This is local authorization evidence, not real coturn, network-media, or production-capacity proof.
|
||||
- Chrome 151 synthetic `1/3/5/8` and 720p30 runs preserved bounded fanout and decoding. A `9461e20`-era three-Viewer rerun kept Host2/Browser Viewer1, decoded every Viewer, and recovered a hard first-level relay departure in 5,380 ms; it did not exercise quality-triggered MBB. Sixteen-Viewer cap2/cap3 loopbacks decoded all Viewers and a ten-second follow-up recorded guarded sender and aggregate Chromium CPU evidence, but resolution/FPS remained low and the ordinary-PC data cannot rank caps, select product policy, or prove sustainable heterogeneous-network quality. See [peer-assisted media](./research/peer-assisted-media.md).
|
||||
- Chrome 151 with local LiveKit 1.13.5/client 2.22.0 proved one SFU/UDP root after `q,f` -> `q,h`: decoded frames advanced 3 -> 23, rendered frames reached 26, Host used one edge, leaves were clean, and TURN was absent. This is functional evidence only. See [low-server media routes](./research/low-server-media-routes.md).
|
||||
- Host A+B and authenticated P2P Viewer C evidence is sanitized, generation-bound, read-only, and closed for stale, ambiguous, or SFU-fed reports. Production can expose a Host-local current SFU `h` snapshot and clears it on publisher identity changes; raw media metadata is not retained. See [realtime quality adaptation](./research/realtime-quality-adaptation.md).
|
||||
|
||||
+3
-3
@@ -358,7 +358,7 @@ Token-free SFU standby prewarm 保持可选且不创建 participant、publicatio
|
||||
2. 完成 RoomStore、建房 API、WebSocket 鉴权和定向信令。
|
||||
3. 完成屏幕捕获、逐观看者 PeerConnection、观看播放和手动质量档。
|
||||
4. 完成连接恢复和 stats 面板;随后以 STUN-only snapshot 替换旧全房 TURN credential/refresh wire。
|
||||
5. 在已合入的 endpoint cap/accounting、`screener-v6` wire 与 SFU admission/lifecycle 边界上,按 ADR-0005 完成 route waves C-D:建立 TURN allocation admission,并把 deterministic allocation、child reparent 和 parent drain 收到一个 controller;每个 wave 独立可回滚。
|
||||
5. 在已合入的 endpoint cap/accounting、`screener-v6` wire、SFU lifecycle 与 TURN allocation admission 边界上,按 ADR-0005 完成 route controller convergence:把 deterministic allocation、child reparent 和 parent drain 收到一个 controller;该 wave 独立可回滚。
|
||||
6. 路由边界合入后依次落 live screen-audio ceiling 和 paused video-codec transaction;随后做 H.264 根因诊断与 strict-NAT emulator gate,门禁通过才允许 allowlisted canary。
|
||||
7. 加入 first-frame-driven Viewer connection stages。Site access、room-scoped Viewer grant、路由与 SQLite v3 合同保持唯一。
|
||||
8. Windows Native fixed-`HIGH` 保持可选且不改变 Web 默认;shared encode、移动 lifecycle 和平台输出按 TODO roadmap 后续推进。
|
||||
@@ -376,9 +376,9 @@ Token-free SFU standby prewarm 保持可选且不创建 participant、publicatio
|
||||
|
||||
Parent selection 使用硬过滤加字典序,不建立综合质量评分器。先拒绝 stale session、不可 source-reachable、成环、超深、无 sender/overlap slot、relay-ineligible、位于 failed-edge cooldown 或 server resource 未准入的候选;对剩余候选依次比较结果深度、分配后剩余稳态 sender slots、稳定加入顺序与 peer identity。controller 每次只 reserve/prepare 一个候选,使用该 `RTCPeerConnection` 自带的 ICE checklist/connectivity checks,再以 current-generation RTP、live track 与 decoded frame 验证;初次加入或 hard failure 采用达到 media-usable floor 的首个候选,soft-quality reparent 还需 quality owner 证明候选达到 recovery threshold 且优于仍健康旧 edge。失败先幂等清理候选再取下一个;受管 SFU room 完成删除证明前仍占 server capacity。应用不做 all-pairs ping、raw-IP/NAT/地理排名、周期探测或全房重平衡。一个 exact edge 的近期失败只进入该 edge 的有界 exclusion/cooldown,不污染其他路径。
|
||||
|
||||
所有非服务器端点共享一个 server-authoritative steady outbound media-copy capacity:唯一配置 `ENDPOINT_MEDIA_COPY_CAPACITY` 默认 `2`,只接受 `1`、`2` 或 `3`,不兼容旧键。peer child 或 Host publication 各占一份,upstream receive 免费,committed selected TURN 只替换同一份 edge transport;SFU subscriber egress 与 TURN allocation 使用独立 server admission。客户端 capability 只能收紧该值,不能按角色、浏览器、UA、设备或页面可见性建立另一套 policy。服务端通过 v6 `authenticated.endpointMediaCopyCapacity` 把最终值交给 Web 与 Native;Native 不从 `maxViewers` 推导发送预算,普通 admission、peer-assisted child assignment 和槽位分配共用该值。代码通过一个 shared accounting guard 执行,不在 Host、Viewer、active、recovery 或 migration 分支重复 magic number;client/server/native wire 随该能力原子升级。room-wide selected-lease 安全护栏在独立 TURN admission 就绪前继续保留,但不把其固定值当作产品 policy;`C=3` 满载时必须在发出会产生第四份 Host media copy 的 token/grant 前明确等待或失败。
|
||||
所有非服务器端点共享一个 server-authoritative steady outbound media-copy capacity:唯一配置 `ENDPOINT_MEDIA_COPY_CAPACITY` 默认 `2`,只接受 `1`、`2` 或 `3`,不兼容旧键。peer child 或 Host publication 各占一份,upstream receive 免费,committed selected TURN 只替换同一份 edge transport;SFU subscriber egress 与 TURN allocation 使用独立 server admission。客户端 capability 只能收紧该值,不能按角色、浏览器、UA、设备或页面可见性建立另一套 policy。服务端通过 v6 `authenticated.endpointMediaCopyCapacity` 把最终值交给 Web 与 Native;Native 不从 `maxViewers` 推导发送预算,普通 admission、peer-assisted child assignment 和槽位分配共用该值。代码通过一个 shared accounting guard 执行,不在 Host、Viewer、active、recovery 或 migration 分支重复 magic number;client/server/native wire 随该能力原子升级。Selected TURN 使用显式无默认值的正 safe-integer deployment capacity;同一个进程内 ledger 对每条 exact peer-selected edge 和 Host-SFU ingress 在 credential 签发前 reserve `1`,并让 reserved、committed、draining authorization 持续计费至 exact logical release。`C=3` 满载时只阻止会产生第四份 endpoint media copy 的 token/grant;同一 edge 改用 TURN 不增加 endpoint copy,但仍需独立 TURN admission。
|
||||
|
||||
SFU admission 在应用单进程中只有一个注入实例。LiveKit credential tuple 完整时,必须同时显式配置私有 `LIVEKIT_API_URL`、正 safe integer `SFU_INGRESS_CAPACITY` 与 `SFU_EGRESS_CAPACITY`;容量没有产品默认值,也不从 Viewer 数、endpoint cap 或历史 root 数推导。专用 LiveKit 实例设置 `room.auto_create: false`。账本只保存全局已用计数和按 exact room/share/publication generation 索引的 `reserved | committed | draining` 条目:Host publication 计 ingress `1`,每个订阅计 egress `1`,candidate、committed 和未完成 drain 的旧 generation 同时计数。route controller 先 reserve,再通过 `RoomService.CreateRoom` 创建 exact-generation room,成功后才 prepare 和签发 token;media proof 后 commit candidate 并把旧 generation 转入 draining,失败、超时、失联、分享换代、停止或删房也只转入同一状态。只有 `RoomService.DeleteRoom` 成功且 follow-up lookup 证明 room 不存在,账本才扣除对应资源;auto-create 关闭后,旧 token 不能重建已删除 room。进程启动在接受流量前拒绝任何非 Screener room,删除全部遗留 Screener room 并确认 namespace 为空;关闭时先 drain 再遗忘计数。Host 信令离线期间若 exact room 中的 Host participant 仍存在就继续计费并保留健康媒体,participant 消失后在一个有界轮询周期内回收。稳态 reserve/commit/drain bookkeeping 仍是 Map lookup 与整数加减;只有 generation 创建、删除、启动清场和 Host 离线检查访问 LiveKit control plane。当前切片不实现 TURN allocation admission,不改 parent selection,也不预建多进程协调;多应用进程部署必须先增加共享原子 admission/lifecycle owner。
|
||||
SFU admission 在应用单进程中只有一个注入实例。LiveKit credential tuple 完整时,必须同时显式配置私有 `LIVEKIT_API_URL`、正 safe integer `SFU_INGRESS_CAPACITY` 与 `SFU_EGRESS_CAPACITY`;容量没有产品默认值,也不从 Viewer 数、endpoint cap 或历史 root 数推导。专用 LiveKit 实例设置 `room.auto_create: false`。账本只保存全局已用计数和按 exact room/share/publication generation 索引的 `reserved | committed | draining` 条目:Host publication 计 ingress `1`,每个订阅计 egress `1`,candidate、committed 和未完成 drain 的旧 generation 同时计数。route controller 先 reserve,再通过 `RoomService.CreateRoom` 创建 exact-generation room,成功后才 prepare 和签发 token;media proof 后 commit candidate 并把旧 generation 转入 draining,失败、超时、失联、分享换代、停止或删房也只转入同一状态。只有 `RoomService.DeleteRoom` 成功且 follow-up lookup 证明 room 不存在,账本才扣除对应资源;auto-create 关闭后,旧 token 不能重建已删除 room。进程启动在接受流量前拒绝任何非 Screener room,删除全部遗留 Screener room 并确认 namespace 为空;关闭时先 drain 再遗忘计数。Host 信令离线期间若 exact room 中的 Host participant 仍存在就继续计费并保留健康媒体,participant 消失后在一个有界轮询周期内回收。稳态 reserve/commit/drain bookkeeping 仍是 Map lookup 与整数加减;只有 generation 创建、删除、启动清场和 Host 离线检查访问 LiveKit control plane。TURN allocation 使用独立的进程内 logical ledger;多应用进程部署必须先增加共享原子 admission/lifecycle owner。
|
||||
|
||||
普通 Web relay 把收到的 remote track 加入独立 downstream `RTCPeerConnection`,因此可能逐跳解码和重编码;浏览器不保证跨连接 shared encode。每条 ordinary child 是独立网络副本,实际 encode time、CPU/GPU、bitrate、loss、frame rate、depth 和 recovery 必须测量。
|
||||
|
||||
|
||||
+2
-1
@@ -132,7 +132,7 @@ SFU/TURN 的 publication、subscription、transport、server-resource accounting
|
||||
|
||||
### 一对多与带宽保护
|
||||
|
||||
- Given `ENDPOINT_MEDIA_COPY_CAPACITY=C`,其中 `C` 只能是 `1`、`2` 或 `3` 且默认 `2`,When Host 或任一 Viewer 建立、恢复、重鉴权或迁移媒体路径,Then peer child 与 Host publication 的稳态实际发送副本总数不超过 `C`,upstream receive 不计数,committed selected TURN 不重复计数,角色、浏览器和 UA 不改变 `C`;每个 `authenticated` 快照都携带同一个 `C`,Native Host 不用 `maxViewers` 或本地常量代替它,并行候选只有持有 `TransitionOverlapSlot` 时才可达到 `min(C + 1, 3)`,并在 commit/abort 后释放。When 此能力合同上线,Then client/server/native wire 同一 release 原子升级,缺失或越界的 `C` 与旧 wire 都在房间授权前得到明确 mismatch,且 `C=3` 满载 Host 在取得第四份 publication/token/grant 前明确等待或失败。
|
||||
- Given `ENDPOINT_MEDIA_COPY_CAPACITY=C`,其中 `C` 只能是 `1`、`2` 或 `3` 且默认 `2`,When Host 或任一 Viewer 建立、恢复、重鉴权或迁移媒体路径,Then peer child 与 Host publication 的稳态实际发送副本总数不超过 `C`,upstream receive 不计数,committed selected TURN 不重复计数,角色、浏览器和 UA 不改变 `C`;每个 `authenticated` 快照都携带同一个 `C`,Native Host 不用 `maxViewers` 或本地常量代替它,并行候选只有持有 `TransitionOverlapSlot` 时才可达到 `min(C + 1, 3)`,并在 commit/abort 后释放。When 此能力合同上线,Then client/server/native wire 同一 release 原子升级,缺失或越界的 `C` 与旧 wire 都在房间授权前得到明确 mismatch,且 `C=3` 满载 Host 在取得会产生第四份 endpoint media copy 的 publication/token/grant 前明确等待或失败。
|
||||
- Given peer-assisted 路径分别运行 1、3、5、8 名观看者,When 用户加入、容量释放、节点离开、重鉴权或当前 edge 失效,Then 服务端只为新 Viewer、等待 Viewer 或失去 parent 的 subtree root 选择一个 active parent;每名 Viewer 同时至多一个 active upstream,活动图无环,其余健康边保持 sticky。没有可用 parent 时明确等待或拒绝,不主动重平衡或引入常驻多源媒体。
|
||||
- Given 一名分享者和八名观看者,When 在受控网络中运行已记录的质量档位,Then 记录每条边的拓扑深度、候选类型、码率、编码/解码负载、分享端与 relay 上行、首帧和玻璃到玻璃延迟;该条在真实矩阵完成前保持未验收。
|
||||
- Given candidate 改变房间 admission 默认值或上限,When 在目标数量与代表性路径上运行规定时长并注入 relay departure、重连和一个弱路径,Then 每名观看者持续解码、每个非服务器端点不超过配置容量、深度与故障半径有界、未受影响 subtree 不迁移,并记录端点与中央服务的 CPU、GPU、内存、上行、出口、帧率、丢包率、冻结和恢复;任一门槛失败时不得切换默认值。
|
||||
@@ -142,6 +142,7 @@ SFU/TURN 的 publication、subscription、transport、server-resource accounting
|
||||
- Given 新观看者会使预计总上行超过安全预算,When 其请求加入,Then 系统只选择整体路由模型已授权且满足配置容量与资源准入的路径;没有合格路线时明确等待或拒绝,而不是创建超过配置容量的 ordinary edge 或持续堆积发送队列。各 transport 的拥塞控制适应该路径,应用证据只改变拓扑资格,不能合成全房降档。
|
||||
- Given SFU 或 TURN 参与路线,When 计算准入、迁移 overlap 或失败恢复,Then 同时检查统一端点容量和独立的 server ingress/egress、SFU、TURN 资源预算;不得把普通端点 child 数当作 server cap,也不得借兜底形成无界整房 fanout。
|
||||
- Given 配置完整 LiveKit credential tuple,When `LIVEKIT_API_URL` 缺失或不是允许的 control-plane origin,或 `SFU_INGRESS_CAPACITY` / `SFU_EGRESS_CAPACITY` 缺失、非正整数或超出 JavaScript safe-integer 范围,Then 服务必须在启动时 fail closed。Given 配置有效,When startup listing 出现非 Screener room、遗留 room 无法删除、删除后仍存在,或 exact candidate room 无法显式创建,Then 应用不得签发 token 或接受可能重复计算的 SFU generation。Given 当前 reserved、committed 与 draining 的 ingress 或 egress 会越过任一部署容量,Then controller 必须在签发任何新 SFU token 前拒绝该 candidate,并保持旧 route 和计数不变。Given generation 被 commit、abort、timeout、stop、delete 或 Host participant 离线回收,When DeleteRoom 尚未成功或 absent readback 尚未完成,Then 它必须继续占用账本资源且旧 token 不能创建 room。
|
||||
- Given 配置 selected TURN,When 四项 tuple 不完整或 `SELECTED_EDGE_TURN_ALLOCATION_CAPACITY` 不是正 safe integer,Then 服务在启动时 fail closed。Given 配置有效,When exact peer-selected edge 或 Host-SFU ingress 申请 credential,Then 同一个 deployment ledger 必须先 reserve `1`,并让 reserved、committed、draining authorization 持续计费至 exact logical release;容量耗尽保持旧 route 并走现有有界候选、等待或失败。Given stale room/share/session/revision/connection identity、重复 release、停止分享、删房或 shutdown,Then 只能释放匹配 authorization,不能误扣其他 edge。
|
||||
- Given Host、relay parent 或 leaf 处于受限网络,When direct/peer 路径不足,Then 只执行 ADR-0005 授权的 publisher、subscriber、selected transport 和 fallback sequence;不得靠未授权的固定数量或静态 lease 假设猜测实现。
|
||||
|
||||
### 质量和恢复
|
||||
|
||||
Reference in new issue
Block a user