Repository navigation
[Runtime Architecture][Phase 18] 完成 public API/package 审计、发布门禁与迁移文档 #86
Description
总跟踪:#67
分析基线:main@201b1621cc706ee221e10ac20947af5fc62b087e
阶段依赖:Phase 16 #84、Phase 17 #85
建议交付:一个聚焦 PR;可拆为多个 commit,但合并时不得保留新旧双路径。
Use case
Runtime 生命周期收敛完成后仍需决定 RuntimeContext concrete type、Generated Catalog、Telemetry/SharedMemory 等边界,并为新 major 建立 public API baseline、package validation 和完整 migration 文档。Breaking release 是清理机会,但不是把所有可能拆包都绑在一起的理由。
Proposed behavior
本阶段按下述工程原则和任务清单实施。目标不是增加抽象数量,而是减少非法状态、所有权分支、并发状态组合与测试不确定性。
通用工程原则(本阶段必须遵守)
- 让非法状态不可表示。 构造完成的对象必须立即合法;握手结果、BuildPlan、拓扑和其他稳定配置使用 immutable snapshot 一次发布,不依赖调用顺序完成二次绑定。
- 单一所有权、单一终态。 每个 transport、counter、lease、timer、后台任务和构建期资源都必须写明谁创建、谁拥有、哪个终态释放、停止或失败时由谁等待/观察;竞争终态必须由同一个 winner 收敛,禁止重复释放和 underflow。
- 分离状态域。 Session 的 transport/protocol 状态、ClientConnection 的新调用资格、ServerConnectionState 的认证/调用排空状态分别建模,不用一个布尔值或一个巨型状态机互相冒充。
- 并发必须有界且可监督。 不引入无界队列、无限重试或无人等待的 fire-and-forget;framework-owned detached task 必须登记、观察异常,并在 owner 停止时可 drain。批量 drain 前先关闭 owner-level 写入门槛。
- 统一时间语义。 UTC 只服务 wire deadline、日志、Activity 和公开诊断;本地 deadline、elapsed、heartbeat、retry、breaker、drain 和 shutdown budget 使用同一
TimeProvider的 monotonic timestamp,并能用 fake time 确定测试。 - 资源构建是事务。 Builder 先编译完全验证且不可变的 plan,再 materialize resource,最后 commit 所有权;失败时保留 primary exception,并按登记逆序恰好清理一次。Caller-owned 资源不得被框架擅自释放。
- 保护热路径。 继续读取 immutable snapshot,不增加全局锁;supervisor、BuildPlan、ManifestSource 查询不得进入每次 RPC/每帧/每 item 路径;不得引入无依据的每调用 allocation 或新的锁竞争。
- 明确兼容性边界。 默认保持 Protocol v2 wire format、Contract ID/Method ID/DTO member ID 与 schema 规则;CLR/source API 和 Generated ABI 可以 breaking,但必须显式升级版本、注册/启动阶段 fail fast,且不保留 legacy constructor、Default Context、reflection adapter 或旧 ABI 转接层。
- 增量实施、独立验证和回滚。 每个阶段对应一个聚焦 PR,可单独测试、基准和回滚;不一次性重写 Runtime,也不为了目录整齐或抽象形式扩大范围。
- 保留已经正确的并发模式。 例如
StreamManager.CompleteAll先 CAS 发布终态再逐 stripe drain、PendingCall单槽位终态竞争、dispatcher acquire/close/detach lease;不得以“统一”为名改成全局锁或ConcurrentDictionary全面替换。 - 测试与诊断先行。 生命周期变更必须有竞态、fault-injection、fake-time、stress/chaos、ALC/NativeAOT(按影响范围)测试;触及热路径时必须提交 BenchmarkDotNet 前后数据。
- 每个新增可变状态都回答四个问题。 谁创建?谁拥有?哪个终态释放?停止/失败时如何被等待和观察?无法用一两句话回答时不得合并。
本阶段任务
- 审计
SharpLinkRuntimeContext/ Builder 是否仍需普通 public;优先通过 Client/Server Builder 暴露 runtime/codec/time 配置。若 Generated ABI 需要 context,放入明确 ABI namespace/interface。 - 审计
SharpLinkGeneratedAssemblyCatalog:业务用户不直接操作 process catalog;generated bootstrap 使用明确、版本化 infrastructure entrypoint,必要时EditorBrowsable(Never)。 - 评估 SharedMemory 独立 package(实验性、unsafe/platform-specific 边界)和 Telemetry 子系统归属;只有能实际降低依赖/AOT rooting 且 package graph 稳定时拆分。TCP/NamedPipe/Telemetry 拆分不阻塞本轮。
- 为
SharpLink.Abstractions、Runtime、Client、Server、Hosting 建立新 major public API snapshot/baseline;API 删除/新增必须显式 review。 - 建立新 major package validation,不要求旧 major binary compatibility,但发布后以新 baseline 稳定。
- 完成 source migration table:删除/改名、builder single-use、transport/session 入口、RuntimeContext、Generated ABI 重新生成、ownership/Dispose 变化。
- 同步
doc/architecture.md、doc/calls-and-streaming.md、doc/dynamic-modules-and-multicluster.md和所有受影响 sample/XML docs。 - 执行总完成定义审计:全仓搜索 legacy constructor、Default/Bind/SetTelemetrySide、old ABI adapter、public engine mutator、Task.Yield polling、wall-clock local timeout、重复 rollback/counter。
- 汇总 Release build、unit/generator/integration、AOT、Chaos、ALC、MultiCluster、Streaming、benchmark 和 Protocol/schema compatibility 结果,作为 breaking release gate。
交付物
- Public API/package/telemetry/shared-memory ADR 或审计结论。
- 新 major API/package baseline、完整 migration guide 和同步架构文档。
- 全阶段 DoD 与性能/兼容性发布报告。
验收标准
- Public API 只保留业务调用、配置、诊断与真实可实现扩展 SPI;engine/generated-only surface 已正确归类。
- 新 major API/package baseline 建立,所有 breaking diff 有意且有迁移条目。
- 是否拆 RuntimeContext/Catalog/SharedMemory/Telemetry 有证据与 ADR,不为“拆得漂亮”强行扩大范围。
- 三份核心架构文档、samples、XML docs 与实现一致。
- Protocol v2、contract/schema、NativeAOT、ALC、Chaos、Integration、MultiCluster、Streaming 与 benchmark 门禁全部通过。
- 总跟踪 issue 的完成定义全部勾选后才能关闭。
本阶段补充验证
- 运行全部通用门禁及影响范围 smoke/chaos/ALC/AOT。
- 汇总所有热路径基准,与 Phase 00 baseline 对比并解释噪声/变化。
- 验证发布包只包含预期 public surface 和当前 generated artifacts。
通用验证门禁
基础门禁(按本阶段影响范围运行,并在 PR 中记录命令与结果):
dotnet build Sharplink.slnx -c Release
dotnet test --project test/SharpLink.UnitTests/SharpLink.UnitTests.csproj -c Release
dotnet test --project test/SharpLink.Generator.Tests/SharpLink.Generator.Tests.csproj -c Release
dotnet run --project test/SharpLink.IntegrationTests/SharpLink.IntegrationTests.csproj -c Release -- --timeout 120s触及 Session、Transport、TimeProvider、DynamicModule 或 generated ABI 时,补充相关的 SharpLink.AotSmoke、SharpLink.ChaosTests、TransportConnectionIntegrationTests、RuntimeAssemblyIntegrationTests、RuntimeMultiClusterIntegrationTests、SendPumpTests、RpcSessionLifecycleTests、StreamManagerTests。
若改动进入 Unary 调用、PendingRequestTable、StreamManager、SendPump、P2C 或 codec resolve 热路径,必须提供 BenchmarkDotNet 前后对比:不得无说明增加每调用 allocation;吞吐回退超过基准噪声(CI 稳定前人工参考 3%–5%)时阻塞;p99 不得出现由新抽象引起的锁竞争。
Compatibility and performance impact
CLR/source/Generated ABI breaking 通过 migration guide 管理;Protocol v2 与 schema 默认保持。新 major 发布后重新稳定 API baseline。Package 拆分只在有依赖/AOT收益时实施。
风险与回滚
将太多 package/telemetry 清理绑进 release 会扩大风险。无法证明收益的拆分记录为后续 ADR/issue;不得阻塞已完成的 lifecycle 收敛。文档不能用兼容 shim 替代。
Out of scope
不在此 issue 重新实现前面阶段;发现缺口应重开/回到对应阶段 issue,而非在最终 PR 混入大规模生产重构。
Alternatives considered
不采用长期保留 legacy constructor、obsolete forwarding overload、Default Context、Runtime reflection adapter、旧 Generated ABI adapter、无界任务/队列或全局锁的方案。若真实扩展需求出现,应设计窄而稳定的新 SPI;若阶段实现需要扩大到无关 package/子系统,应另开 issue 并给出可验证收益。
Checks
- 已搜索现有 Issues 与当前文档,未发现同一实施阶段的重复 issue。
- 本 issue 保留了原实施方案的阶段任务、通用原则、验收、兼容性、性能和回滚约束,并补充了可执行细节。
Activity
SunSi12138 commentedon Aug 10, 2026
Implementation Supplement — Phase 18 执行手册(基于
dev,保留原正文)0. 当前
dev已经发生的重要前置变化开始 Phase 18 时不要按旧
main假设审计:2.0.0;SharpLink.Sdk依赖SharpLink.Abstractions,并明确禁止直接依赖 Runtime;SharpLinkRuntimeContext.Default/ Session 二阶段 Bind 已由前置 phase 删除;dev。所以 Phase 18 的 preflight 要以前序 issue最终实现状态为准,而不是重新搜索一个本来就已删除的旧机制然后把删除动作算成本 phase成果。
1. DoD preflight:逐 phase确认最终不变量
至少确认:
注意 #85 的完成状态不应机械写成“必须有 API 5”。如果 #84 没改变 generated-visible ABI,API 4 可以继续是最终 v2 Generated ABI;Phase 18只要求这个决策有证据并完成兼容矩阵。
若任一项未完成:记录缺口并回对应 phase,不在最终 PR 中顺手做大块 production 重构。
2. 先生成 public API inventory,再做删/留/拆包决策
逐 package:
SharpLink.AbstractionsSharpLink.RuntimeSharpLink.ClientSharpLink.ServerSharpLink.HostingSharpLink.SdkSharpLink.Serializer.SharpPack每个 public type/member分类:
保留 public 的每一项必须回答:真实用户场景、谁实现/调用、ownership、版本负担。
“tests/generated现在使用”本身不是 public理由。
3.
SharpLinkRuntimeContext的最终公开性按真实 use case决定当前
dev的 RuntimeContext 已经:Phase 18 要判断的不是“怎么删除 Default”,而是:
IRpcRuntimeContext是否仍是公开 SPI / client-stream extension需要的能力;有真实use case就保留窄 abstraction;没有就收缩。不要按类型名审美做决定。
4. Generated Catalog 最终边界
在 #83/#85 后重新审计:
SharpLinkGeneratedAssemblyCatalog.Register/CreateSnapshot;如果仅 generated infrastructure需要:明确标成 infrastructure(namespace/EditorBrowsable/docs),不要宣传为普通用户可变 Runtime registry。
不能让用户通过 process catalog直接改变一个已构建 Runtime instance的 ownership/snapshot。
5. SharedMemory / Telemetry 拆包:先证据,后决策
SharedMemory先量化:
Telemetry先确认当前是否只是BCL
Activity/Meter;若没有实质 transitive dependency可消除,拆包可能只增加接口复杂度。结果可以是
defer/no split;这是合格结论。不要为“包更漂亮”扩大 major release风险。6. 新 major API/package baseline
当前
dev已经:但开工时仍要检查各 csproj/props 是否已经设置可执行的
PackageValidationBaselineVersion;不要只因EnablePackageValidation=true就认为 v2 baseline完整。对新 major:
不要引用尚未发布、NuGet不可获取的 baseline导致 pack无法执行;也不要临时关掉全部 package validation后忘记恢复计划。
7. API diff 与 migration table 一一对应
至少记录:
重点:
intentional public deletion没有migration条目时阻塞,除非明确记录“accidental API removed; no replacement”。
8. 把 architecture completion 搜索做成脚本,而不是人工一次性检查
建议
eng/verify-runtime-architecture.sh或并入现有 gate,至少检查:允许的历史名称(migration docs/fixtures)用“路径 + 原因”明确 allowlist;不要
grep || true。9.
dev当前 package verification 的真实基础现有
eng/verify-packages.sh当前验证:.nupkg/.snupkg配对;SharpLink.Abstractions同版本;SharpLink.Runtime;Microsoft.Extensions.DependencyInjection.Abstractions;此外
dev已有专门脚本:eng/verify-abstractions-package-dependency.sheng/verify-generated-assembly-dependencies.sheng/verify-hosting-package-dependency.sheng/verify-generated-abi-mixing.sheng/verify-protocol-v2-cross-version.sh不要把 package gate 写回旧的“SDK→Runtime必须存在”规则。那会逆转已经完成的 SDK/Runtime 解耦。
Phase 18 在现有基础上补:
10. Generated ABI release gate 使用当前已有fixtures,不要从零重造
复用:
若 #85 bump到新的 ABI,再冻结当前 API4 fixture;若不 bump,则不要制造无意义 fixture/version churn。
Release报告必须明确:
11. 文档审计
同步:
doc/architecture.mddoc/calls-and-streaming.mddoc/dynamic-modules-and-multicluster.mddoc/releasing.mddoc/migration.md检查不能再暗示:
12. 最终验证按层执行
Layer A — compile/API/package shape
再跑 architecture verifier、API diff、package-dependency/ABI scripts。
Layer B — behavior
Integration transports、streaming、auth/interceptor/retry/admission、dynamic assembly/multi-cluster、drain/cancel/deadline、fault/rollback。
Layer C — runtime safety
NativeAOT、collectible ALC、Chaos、clean-cache package smoke、platform matrix。
Layer D — release evidence
final performance matrix、soak、package verify、NuGet audit/security、exact SHA + environment capture。
Layer A失败就不要继续长时间 soak。
13. 性能:最终发布回归门禁,不要求每个重构变快
比较 final RC 与项目认可的精确基线,关注 unary/streaming/Pending/StreamManager/SendPump/P2C/codec/compression/transports。
要求:
14. Phase 18 完成条件
发现前序缺口时回对应phase修复并重新跑审计;不要在最终 release PR 混入大规模 Runtime实现修改。
SunSi12138 commentedon Aug 12, 2026
新增前置 cleanup:#161
Hide generated Proxy/Stub implementation types from IntelliSense。建议在本 Phase 18 的 final public API/package baseline freeze 之前合并 #161。原因是当前 generated
*_Proxy/*_Stub仍是顶层 public implementation types;#161 会在不改 Protocol v2、contract/schema 或 Runtime factory semantics 的前提下,把它们收进 generated owner 的 private nested implementation surface。如果 #86 先基于当前 generated concrete types 建立新 major public API baseline,再处理 #161,会人为制造第二次 breaking API diff 和 migration noise。因此建议顺序:
#161 不是性能实验,不需要 old/new 双路径或 runtime fallback;若实现阶段发现 generator/AOT/manifest 有硬约束,应在 baseline freeze 前修正设计,而不是保留 public compatibility shim。
SunSi12138 commentedon Sep 10, 2026
补充 release/versioning policy(来自 #658 review 后确认):
SharpLinkClientSupportSnapshot.CurrentSchemaVersion从 1 改成 2。这个变更在当前开发阶段不需要保留;后续 Phase 18 / release baseline 整理时应改回开发线应有的 schema version,并只在正式发行版本确实需要不兼容 schema bump 时统一升级。这里先记录,不回滚 #658 已合并功能;后续在 #86 的 release/public-surface closure 中统一清理并验证 golden/package/migration 版本策略。
SunSi12138 commentedon Sep 12, 2026
#654 public API / migration note
PR #667 adds a structured, non-throwing control-plane path for live runtime configuration updates.
SharpLinkRuntimeConfigurationUpdateResultwith stableSharpLinkRuntimeConfigurationUpdateFailureCodevalues for expected runtime rejection (LifecycleClosed,ModeConflict,PublicationConflict,UnsupportedByImplementation,CandidateRejected).Try...extension methods. These are additive; the existing throwing runtime-control APIs remain available for source compatibility.ISharpLinkClient/ISharpLinkServerimplementations that do not expose the built-in runtime update capability receiveUnsupportedByImplementationfrom the structured extension path instead of usingNotSupportedExceptionas the normal branch.Migration: orchestration/control-plane callers that currently catch
InvalidOperationExceptionfor expected lifecycle/mode/publication rejection should prefer the newTry...APIs and branch onFailureCode. Existing callers can remain on the throwing APIs until migrated.Tracking implementation/validation: #654 / PR #667.
SunSi12138 commentedon Sep 12, 2026
#654 / PR #667 public API & migration record
SharpLinkRuntimeConfigurationUpdateResultandSharpLinkRuntimeConfigurationUpdateFailureCodeas the canonical machine-readable contract for expected runtime-configuration publication rejection.Try...structured runtime-control paths across the built-in Client/Server public surfaces audited by [api][runtime-config] 运行时配置的预期拒绝改为 structured result #654. Expected lifecycle/mode/publication/unsupported conditions return failure codes; callers must not branch on diagnostic message text.InvalidOperationExceptionfor normal hot-update races should switch to the correspondingTry...path and branch onSucceeded/FailureCode.Tracking implementation: #654, PR #667.
SunSi12138 commentedon Sep 12, 2026
Phase 18 release preparation is in #670 (latest documentation head 2fb9d61; production/test fixes at 570d0e2).
Completed: actual-nupkg public/protected snapshots for all eight shipping packages including SDK forwards; published NuGet 1.1.1 snapshots with download hashes and a full breaking diff; explicit 2.x package-validation baseline policy; public API/RuntimeContext/Catalog/SharedMemory/Telemetry ADR; migration table and the three architecture documents; version calibration from published 1.1.1 (16 checked declarations); removal of the unused Default Context, accidental CompileSymbols API, and unused legacy descriptor constructor. API deletion and unreviewed version negative controls both reject as intended.
Validation evidence: local Release build has zero warnings/errors; unit Passed: 1802, Failed: 0, Skipped: 0; generator Passed: 264, Failed: 0, Skipped: 0. Nine dynamic-module tests passed individually and 50 bounded stream-exit diagnostic cases passed. Release Gate run 34710411637 has successful actual-package checks, protocol process gate, and macOS matrix after fixing the fixture timeout-policy omission and limiting hosted test concurrency. Final workflow summary and final-main validation are still pending.
Actions run 34709801796 is running the TCP/SharedMemory five-hour release soaks and dynamic-module churn. It is pending, not passed. The earlier 0f2e29a soak was superseded and cancelled after the newer code's jobs were running. Browser/Mono/WASM remains investigation evidence under #253; desktop success does not assert Browser interoperability.
Remaining before closure: merge dev to main; validate the final main package set; execute the published-1.1.1 → 2.0 → published-1.1.1 macrobenchmark with a server fixed to four distinct physical cores and VM/Mac clients; publish from main and verify the eight NuGet packages. The user explicitly permits publication while the five-hour Actions soak is still running once other validation is complete; post-release completion/failure will be followed separately.
SunSi12138 commentedon Sep 12, 2026
Release closure update: PR #672 fixes the disconnect/registration topology-lock cycle found while investigating the failed Windows chaos gate. Connection failure/disposal now runs in supervised asynchronous cleanup after detachment, with registration protected against shutdown sealing; ordinary calls skip unrelated planned-refresh locks. Fixed/static/dynamic pools all have regression coverage: all six new cases fail against the old production implementation and pass with the fix. Full local suites passed (1808 unit, 451 integration), plus Release build (0 warnings/errors), formatting and architecture/version/maintainability gates.
Fresh three-platform Release Gate: https://github.com/SunSi12138/SharpLink/actions/runs/34711925108 (pending). Main release PR #671 remains blocked until this fix is incorporated and validated. The existing five-hour TCP/shared-memory Actions jobs are still running; no pending/cancelled soak is being recorded as passed. Formal published-1.1.1 → final-main-2.0.0 → published-1.1.1 ABA remains scheduled after final release validation and before publication, using four physical server cores and VM/Mac clients. No tag or NuGet 2.0.0 publication yet.
SunSi12138 commentedon Sep 13, 2026
Final 2.0.0 release-candidate sync — 2026-09-13
The implementation/public-surface closure is now complete and the final reviewed
devtree has been promoted tomain.Final runtime/client tail after the earlier Phase 18 work:
TimeBudgetonce at frame creation; removed SendPump deadline rewriting and added batch coalescing.Repository state:
dev:708b9d5f286e2047891cd960c6ea8e85cda1498a;mainwith no source-tree delta;main:ac36ba4526bbd54f43c6c19e3419ed4e1a1cf9d2;rpc-oneway-sharedmemory-c1~800 B/op with 0.344 B/op spread).Browser/Mono raw-layout incompatibility evidence remains separate and non-blocking for this 2.0 release contract; the desktop/CoreCLR compatibility and release package gates are green.
Phase 18 implementation, API/package audit, migration/docs and release-candidate validation are therefore complete. The only remaining release-operation step before closing #86 is the actual 2.0.0 tag/NuGet publication from
mainand verification of the eight published packages. No further production-code change is expected for this issue.SunSi12138 commentedon Sep 13, 2026
2.0.0 release closure
SharpLink 2.0.0 is now published.
Final release state:
devfinal reviewed tree:708b9d5f286e2047891cd960c6ea8e85cda1498a.main; merge commit:ac36ba4526bbd54f43c6c19e3419ed4e1a1cf9d2.v2.0.0/ SharpLink 2.0.0 has been published frommain.SharpLink.Abstractions,SharpLink.Runtime,SharpLink.Sdk,SharpLink.Serializer.SharpPack,SharpLink.Client,SharpLink.Compression.Zstd,SharpLink.Server, andSharpLink.Hosting.With the release tag and NuGet publication complete, the remaining Phase 18 release-closure conditions are satisfied. Closing this issue as completed.