Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 15 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

### 修复

- 升级官方 StreamFrame 2.6.0,使用 <code>FrameError</code> 自带的来源
Session ID 关联四种成帧故障,并保留实际观测字节数与截断状态;迟到旧
会话故障不再依赖回调时的当前会话推断。
- SecsFrame 对四种故障统一只复制最多 8 KiB 前缀,避免重同步丢弃样本形成
无界诊断数据,同时保留上游实际字节数供完整性判断。
- 升级官方 StreamFrame 2.5.0,采用自适应发送编码缓冲,并获得 Passive
接受循环代次门控,避免显式关闭与自动重连竞速泄漏监听器。
- 增加真实 TCP Passive 重连竞态测试,连续验证监听恢复、Session ID 单调
Expand All @@ -24,14 +29,17 @@
- 增加真实 TCP Active/Passive 重复会话抖动故障注入测试;固定三轮断开与
重选并复用相同 System Bytes,验证待处理事务确定中断、旧回复与强制迟到
T3 回调不污染替换会话,且新事务可成功完成。
- 增加默认关闭的独立 T8 transport fault 观测流,保留 StreamFrame TCP
Session ID、actor 状态与最多 8 KiB 的未完成帧前缀快照。
- T8 观测队列容量显式可配且满时丢弃最旧项,不阻塞协议 actor;默认路径
- 增加默认关闭的独立 transport fault 观测流,覆盖 DecodeFailed、
DiscardedByResync、IncompleteFrameOverflow 与 IncompleteFrameTimeout,
保留 StreamFrame TCP Session ID、actor 状态、实际字节数、截断状态与最多
8 KiB 的前缀快照。
- 故障观测队列容量显式可配且满时丢弃最旧项,不阻塞协议 actor;默认路径
不创建该通道,旧会话观测不会归入替换会话。
- 增加独立 <code>SecsFrame-TransportFaultTrace/1</code> 信封,沿用
MetadataOnly、RedactedPayload 与 RawPayload 分级,payload codec 默认关闭。
- 增加真实 TCP T8、Session 过滤、队列容量、黄金向量、脱敏复核、防御性
复制和资源限制测试;快照不声明完整 TCP 片段且不能进入重放路径。
- 将独立信封升级为 <code>SecsFrame-TransportFaultTrace/2</code>,新增实际
字节数和 Complete/Truncated 字段,沿用 MetadataOnly、RedactedPayload
与 RawPayload 分级;严格 codec 不读取 v1,也不会推断旧记录完整性。
- 增加四种故障、真实 TCP T8、跨 Session 过滤、8192/8193 字节边界、队列
容量、黄金向量、脱敏复核、防御性复制和资源限制测试;快照不进入重放路径。
- 增加独立 <code>SecsFrame-FaultSampleTrace/1</code> 信封,为公共
<code>DataMessageDecodeFailed</code> 事件提供已成帧 HSMS data body 样本。
- 捕获必须显式选择 MetadataOnly、RedactedPayload 或 RawPayload;默认 codec
Expand Down
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<PackageVersion Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" />
<PackageVersion Include="PolySharp" Version="1.16.0" />
<PackageVersion Include="Secs4Net" Version="3.1.0" />
<PackageVersion Include="StreamFrame" Version="2.5.0" />
<PackageVersion Include="StreamFrame" Version="2.6.0" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="4.0.0" />
</ItemGroup>
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ Equipment 应用发送策略的 Collection Event、报警目录查询、单报
显式启用的完整控制消息观测流或既有未认领控制事件的十字节头元数据。
解码失败样本另用独立信封,并以元数据为默认导出边界;Body 捕获与 codec
导入导出都必须显式开启,声明的脱敏字节范围会固定清零并严格复核。
T8 互操作诊断另有默认关闭、容量有界的独立观测流;它保留 transport
Session ID 和最多 8 KiB 的未完成帧前缀快照。Trace 默认仍只导出元数据,
快照捕获和 payload codec 必须分别显式开启。控制与 T8 观测都和业务事件流
独立;该包不会自行接管任何连接消费者,也不会复用原事务标识。
运输层互操作诊断另有默认关闭、容量有界的独立观测流;它覆盖解码失败、
重同步丢弃、未完成帧溢出和 T8 超时,保留错误来源 transport Session ID、
实际观测字节数、截断状态和最多 8 KiB 的前缀快照。Trace 默认仍只导出
元数据,快照捕获和 payload codec 必须分别显式开启。控制与运输故障观测
都和业务事件流独立;该包不会自行接管任何连接消费者,也不会复用原事务
标识。
Item 用法与边界见
[docs/SECS-II-ITEMS.md](docs/SECS-II-ITEMS.md),消息集成见
[docs/SECS-MESSAGES.md](docs/SECS-MESSAGES.md),传输适配边界见
Expand Down
19 changes: 10 additions & 9 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ Trace 的时序重放必须显式启用,只在允许发送记录之间等待
该流并创建记录,不自行订阅连接。既有公共未认领控制事件工厂继续可用。
已成帧但 SECS-II Body 解码失败的样本使用独立信封:捕获和 codec 分别要求
显式数据边界,默认只允许头与原 Body 长度;payload-bearing 记录不能进入
重放。T8 使用另一个独立信封:核心必须先显式启用容量有界的观测流,Trace
再选择元数据、脱敏或原始前缀快照;快照最多 8 KiB 且不声明完整 TCP 片段。
其他成帧错误仍未进入该模型。
重放。运输成帧故障使用另一个独立信封:核心必须先显式启用容量有界的观测
流,Trace 再选择元数据、脱敏或原始前缀快照;四种错误均保留来源 Session、
实际字节数和截断状态,快照统一最多 8 KiB。

## 核心原则

Expand Down Expand Up @@ -70,7 +70,7 @@ HSMS 会话切换后,旧会话的控制请求、数据事务和等待中的应
<code>IHsmsTransport</code> 使用单一事件流按 Session ID 报告会话打开、
帧到达和会话关闭。<code>StreamFrameHsmsTransport</code> 已在内部实现:

- 直接采用 StreamFrame 2.5.0 的单调 TCP Session ID,并在 Connected
- 直接采用 StreamFrame 2.6.0 的单调 TCP Session ID,并在 Connected
发布点同步分配会话 epoch;
- 通过会话感知接收流保留帧的原始 Session ID,迟到消费不会被标成新会话;
- 会话绑定发送在 StreamFrame 原生 FIFO 中校验 Session ID,旧会话消息
Expand All @@ -80,13 +80,14 @@ HSMS 会话切换后,旧会话的控制请求、数据事务和等待中的应
- Active 连接把显式 T5 映射为固定 StreamFrame 重试间隔,关闭指数退避;
- 显式 T8 映射为 StreamFrame 原生未完成帧超时,并把对应 FrameError
转换为带 transport Session ID 的 HSMS 关闭原因;显式启用时还在同一
transport 事件序列中复制有界前缀快照。
transport 事件序列中发布四种成帧故障的有界前缀和完整性元数据。

这些能力仍隔离在 <code>IHsmsTransport</code> 后,不进入公共 API。此前
跟踪的 StreamFrame #38/#39 已在 2.3.0 完成迁移,2.3.1 进一步封闭迟到
旧故障污染活会话和排队消息跨 Socket 错发的竞态,2.4.0 又收口发布窗口
旧 epoch 故障并加固 Passive 监听恢复,2.5.0 进一步以接受循环代次门控
阻止重连竞速泄漏旧监听器,并加入不改变编码契约的自适应发送缓冲;
阻止重连竞速泄漏旧监听器,并加入不改变编码契约的自适应发送缓冲;2.6.0
再为四种 FrameError 提供统一的来源 Session 与快照完整性元数据;
SecsFrame 只保留协议关闭原因和异常边界转换。详细失效模式与验证证据见
[STREAMFRAME-ADAPTER.md](STREAMFRAME-ADAPTER.md)。

Expand Down Expand Up @@ -141,11 +142,11 @@ Selected 转发数据消息;提前到达的数据、可识别的不支持类
通道默认不创建,记录不含 Body、原始字节、transport Session generation
或时间戳;它是诊断元数据边界,不参与协议决策。

可选 T8 观测通道同样由 actor 写入,但使用容量有界、满时丢弃最旧项的
可选运输故障观测通道同样由 actor 写入,但使用容量有界、满时丢弃最旧项的
独立队列,避免未消费的原始快照形成无界内存或阻塞协议处理。状态机只接受
当前 transport Session ID 的 fault;观测保留最多 8 KiB 前缀,不参与关闭
决策。StreamFrame 2.5.0 的其他 FrameError 不带 session/epoch,核心不会
用读取“当前 ID”的方式把它们冒充为严格会话关联事件。
决策。四种故障都使用 StreamFrame 2.6.0 事件自带的来源 Session、实际字节
数和截断状态;只有 IncompleteFrameTimeout 参与 T8 关闭原因决策。

### 会话绑定的数据事务

Expand Down
5 changes: 3 additions & 2 deletions docs/COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
StreamFrame #38(未完成帧超时)与 #39(会话感知发送确认及消息上下文)
已经随官方 StreamFrame 2.3.0 发布,2.3.1 随后补充迟到旧会话故障隔离、
排队发送 Session ID 复核和稳定失效异常修复。SecsFrame 当前固定官方
2.5.0 NuGet 包;2.4.0 收口 Connected 发布点的会话 epoch,并加固 Passive
2.6.0 NuGet 包;2.4.0 收口 Connected 发布点的会话 epoch,并加固 Passive
接受重试与监听端口重绑;2.5.0 再以接受循环代次门控阻止显式关闭/自动重连
竞速泄漏旧监听器,并采用不改变编码契约的自适应发送缓冲。内部
竞速泄漏旧监听器,并采用不改变编码契约的自适应发送缓冲;2.6.0 为四种
FrameError 统一补充来源 Session、实际字节数和截断状态。内部
<code>StreamFrameHsmsTransport</code> 使用原生会话 API;此前基于
原始字节回调、发送信封和自建 Session ID 的临时实现已经删除。

Expand Down
56 changes: 22 additions & 34 deletions docs/DEVELOPMENT-STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,24 @@ GitHub Issue/Actions:

## 当前基线

截至 2026-08-29,功能基线为 `main` 的 PR #40(提交 `40743c6`):
截至 2026-08-30,本切片基于 `main` 的 PR #42(提交 `64713b7`),升级后
基线为:

- StreamFrame 固定为官方 NuGet `2.5.0`。
- StreamFrame 固定为官方 NuGet `2.6.0`。
- secs4net 互操作测试固定为 nuget.org 官方 `3.1.0`,不得改用源码引用或
非官方包。
- SML 调试读写、已解码消息 Trace 导出、结构化脱敏、受控及时序重放、
诊断/控制元数据 Trace、解码失败样本和 T8 前缀快照均已落地。
- T8 故障观测默认关闭、队列有界,最多保存 StreamFrame 提供的 8 KiB
前缀;它不是完整 TCP 片段,也不能进入消息重放路径。
诊断/控制元数据 Trace、解码失败样本和运输故障快照均已落地。
- 运输故障观测覆盖 StreamFrame 的四种 <code>FrameErrorKind</code>,默认
关闭、队列有界,保留来源 Session、实际字节数和截断状态,并由 SecsFrame
统一只保存最多 8 KiB 前缀;它不能进入消息重放路径。
- <code>SecsFrame-TransportFaultTrace/2</code> 显式保存实际字节数和
Complete/Truncated;严格 codec 拒绝 v1,不对旧记录静默推断完整性。
- 真实 TCP Active/Passive 事务测试固定重复三次断开和重选,复用相同
System Bytes 并强制投递旧 T3 回调,验证旧回复、旧计时器和待处理事务
不会污染替换会话。
- SecsFrame 当前没有开放 Issue。当前 `main` 提交 `8fc4599`(PR #41)的
`ci` 与 `codeql` 均通过。
- 最近一次完整本地验证中,核心测试在 `net48`、`net8.0`、`net10.0` 各
通过 274 项;官方 secs4net 互操作测试在 `net8.0`、`net10.0` 各通过
通过 289 项;官方 secs4net 互操作测试在 `net8.0`、`net10.0` 各通过
2 项。

所有新提交仍须重新运行:
Expand All @@ -45,33 +47,21 @@ dotnet build SecsFrame.slnx -c Release
dotnet test SecsFrame.slnx -c Release --no-build
```

## 当前阻塞

### StreamFrame 错误归属

[StreamFrame #56](https://github.com/CSJ608/StreamFrame/issues/56) 已由
[PR #57](https://github.com/CSJ608/StreamFrame/pull/57) 实现并关闭,但截至
2026-08-29,最新 GitHub Release 与 nuget.org 官方包仍为 `2.5.0`。上游
计划在 StreamFrame `2.6.0` 提供:
## 已解除的上游依赖

- `FrameError` 的原始 transport Session ID;
- 错误发生时的实际观测字节数;
- `Bytes` 快照是否截断;
- 四种 `FrameErrorKind` 一致的来源会话语义,并保留现有兼容性。
[StreamFrame #56](https://github.com/CSJ608/StreamFrame/issues/56) 已随官方
[2.6.0 发布](https://github.com/CSJ608/StreamFrame/releases/tag/v2.6.0)。
SecsFrame 已核对 Release、NuGet 包和实际 API,并完成以下集成:

上游发布前,不扩展 `DecodeFailed`、`IncompleteFrameOverflow` 与
`DiscardedByResync` 的公共运输故障观测。不得用回调时读取的
`CurrentSessionId` 冒充错误的原始会话归属。
- 四种 <code>FrameErrorKind</code> 均使用事件自带的原始 transport
Session ID,迟到旧会话错误不会归入替换会话;
- 公共观测与 Trace 保留 <code>ObservedByteCount</code> 和
<code>IsTruncated</code>,SecsFrame 对所有类型再统一封顶 8 KiB;
- Trace 严格格式升级到 v2,v1 明确拒绝而不是推断缺失字段;
- 四种错误、跨会话、8192/8193 字节、真实 TCP T8、脱敏和严格读取均有
自动化证据。

上游发布后,先核对 Release、NuGet 包和真实 API,再安排一个独立升级切片:

1. 升级 StreamFrame,并确认旧会话迟到错误仍携带旧 Session ID。
2. T8 改用事件自带的来源会话,并扩展其余三种错误类型。
3. 在观测和 Trace 中忠实保留实际字节数与截断状态;需要时升级 Trace
信封版本,不静默改变现有严格格式。
4. 增加四种错误、跨会话、8 KiB 上下边界、脱敏和严格读取测试。
5. 更新 README、路线图、专题文档与 `CHANGELOG.md`,完成完整验证并通过
Pull Request 交付。
## 当前阻塞

### 授权标准材料

Expand Down Expand Up @@ -101,8 +91,6 @@ Primary/Secondary、断开和重选,并验证:

## 状态更新规则

- StreamFrame #56 发布后,将其从“当前阻塞”移入完成基线,并记录实际采用的
StreamFrame 版本和 SecsFrame PR。
- 每个改变路线图优先级或外部阻塞的 PR 都应同步更新本文。
- 已完成能力的长期说明归入对应专题文档;本文只保留继续开发所需的状态,
避免演变成提交日志或聊天记录。
23 changes: 12 additions & 11 deletions docs/HSMS-CONNECTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ StreamFrame 运输适配、HSMS-SS 会话 actor 和数据事务 actor,调用
- Linktest、Deselect 和 Separate 控制命令;
- 状态、数据、未消费控制消息和解码失败的单消费者异步事件流;
- 默认关闭、与业务事件独立的完整控制消息头元数据观测流;
- 默认关闭、容量有界的 T8 transport Session 前缀快照观测流。
- 默认关闭、容量有界的四类运输故障前缀快照观测流。

Host/Equipment 是后续业务能力角色,不由 Active/Passive 推断。
需要按运行期 Stream/Function 处理 Primary 时,可在本事件流上组合
Expand All @@ -38,8 +38,8 @@ Host/Equipment 是后续业务能力角色,不由 Active/Passive 推断。
| T7 | TCP 建立后等待进入 Selected |
| T8 | 未完成消息接收进展等待 |
| EnableControlMessageObservation | 是否创建完整控制消息元数据观测流;默认 false |
| EnableTransportFaultObservation | 是否创建 T8 前缀快照观测流;默认 false |
| TransportFaultObservationCapacity | T8 队列容量;满时丢弃最旧项,默认 16 |
| EnableTransportFaultObservation | 是否创建运输故障快照观测流;默认 false |
| TransportFaultObservationCapacity | 故障队列容量;满时丢弃最旧项,默认 16 |

仓库没有内置或暗示标准默认值。T5 必须能无损转换成 StreamFrame 使用的
整毫秒范围;Passive 监听重试不被解释成 T5。每个取值应依据团队合法获得
Expand Down Expand Up @@ -126,7 +126,7 @@ await foreach (var observation in connection
transport Session generation 或时间戳,也不改变未认领
<code>ControlMessageReceived</code> 业务事件的既有行为。

T8 原始诊断必须另外显式设置
运输故障原始诊断必须另外显式设置
<code>EnableTransportFaultObservation</code>。该流不占用业务事件消费者:

~~~csharp
Expand All @@ -140,13 +140,14 @@ await foreach (var fault in connection
}
~~~

<code>HsmsTransportFaultObservation</code> 保留
<code>IncompleteFrameTimeout</code>、StreamFrame TCP Session ID、actor
观察状态和防御性复制的前缀快照。快照最多 8 KiB,可能包含四字节 HSMS
长度前缀;StreamFrame 2.5.0 不报告原缓冲总长度或完整性,因此不得把它
解释成完整 TCP 片段。队列按配置容量保留最新项,满时丢弃最旧项而不阻塞
协议 actor;应用启用后应持续消费。该观测在对应会话关闭事件处理前写入,
但两个独立异步流之间不承诺消费者可见的全局顺序。
<code>HsmsTransportFaultObservation</code> 覆盖 DecodeFailed、
DiscardedByResync、IncompleteFrameOverflow 和 IncompleteFrameTimeout,
保留 StreamFrame 报告的原始 TCP Session ID、actor 观察状态、实际字节数、
截断状态和防御性复制的前缀快照。SecsFrame 对所有类型统一最多保留 8 KiB;
快照可能为空,也可能包含四字节 HSMS 长度前缀。队列按配置容量保留最新项,
满时丢弃最旧项而不阻塞协议 actor;应用启用后应持续消费。只有 T8 超时会
影响关闭原因,其余观测不改变连接行为。该观测在对应会话关闭事件处理前
写入,但两个独立异步流之间不承诺消费者可见的全局顺序。

带错误的状态事件和解码失败事件还会提供可选
<code>HsmsDiagnostic</code>,用于按稳定代码、层级、操作与计时器处理,
Expand Down
13 changes: 7 additions & 6 deletions docs/HSMS-DIAGNOSTICS.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,13 @@ System Bytes 和远端状态字节仍属于运维元数据,导出文件仍应
带 Body 的导入或导出都要再次显式开启。该信封不包含异常、TCP 长度前缀、
分片、transport Session generation 或 T8 未完成片段。

T8 另有默认关闭的 <code>HsmsTransportFaultObservation</code> 独立流和
<code>SecsFrame-TransportFaultTrace/1</code> 信封。观测只保留当前 T8 所属
transport Session ID、actor 状态和 StreamFrame 已复制的最多 8 KiB 前缀;
队列有界且满时丢弃最旧项。Trace 捕获必须再选择仅元数据、声明范围清零或
原始快照,默认 codec 仍拒绝带快照的记录。它不包含异常、原缓冲总长度、
完整性标记或分片时序,也不能用于重放。
运输成帧错误另有默认关闭的 <code>HsmsTransportFaultObservation</code>
独立流和 <code>SecsFrame-TransportFaultTrace/2</code> 信封。观测覆盖四种
<code>FrameErrorKind</code>,保留错误来源 transport Session ID、actor 状态、
实际观测字节数、截断状态和最多 8 KiB 前缀;队列有界且满时丢弃最旧项。
Trace 捕获必须再选择仅元数据、声明范围清零或原始快照,默认 codec 仍拒绝
带快照的记录。它不包含异常或分片时序,也不能用于重放;v1 因缺少完整性
元数据而由严格 codec 明确拒绝。

## 标准边界

Expand Down
Loading
Loading