mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-08 10:34:51 +00:00
CatalogEntry gains createdAt/updatedAt and the catalog document moves to v5 (reads v1-v5, writes v5). Modification time is structure-sensitive: editing a node's own fields bumps the node, a group's direct child set or order changes bump the group, and a moved node keeps its timestamps. No-op writes and unchanged subscription refreshes bump nothing; the refresh rebuild compares per node, so surviving leaves keep theirs. All times are passed in by callers as now: Date - one moment per logical commit, the domain layer stays clock-free. Legacy documents load with nil (unknown, never backfilled); duplicates and imports stamp fresh times at the moment of the operation. Semantics are recorded as glossary term 节点时间戳 and ADR 0031. No UI in this change.
2.3 KiB
2.3 KiB
配置目录节点记录创建时间与修改时间
Status: Accepted (2026-10-09)
配置目录的每个节点(服务器配置与配置组)增加创建时间与修改时间事实,目录文档版本升至 v5(读取兼容 v1–v5,写入始终 v5)。修改时间采用结构敏感语义(类比目录 mtime):节点自身资料变化(服务器的连接字段与名称、分组的名称)更新自身;分组的直接子节点集合或顺序变化(增删子节点、子节点移入移出、重排)更新该分组;被移动节点自身内容不变、修改时间不动;内容未变的写操作(同名重命名、同值字段提交、内容未变的订阅刷新)不更新任何时间戳。时间一律由调用方传入(now: Date),领域层保持无时钟纯值类型;一次逻辑变更(导入、复制、订阅快照应用)共享同一时刻。
订阅子树同样维护时间戳:订阅刷新以快照整体重建,但逐节点与旧载荷比较——延续且内容未变的节点保留双时间戳,内容变化的保留创建时间、更新修改时间,新出现的节点双时间戳为写入时刻;固定分组身份客户端所有,其创建时间跨刷新保留。复制、URI/文件导入与 Legacy 导入产生的新节点,创建时间即操作时刻,与「全新本地身份」规则一致(ADR-0027)。历史文档(v1–v4)没有时间戳,读取为未知(nil)且不回填,与订阅 lastSucceededAt 的「旧文件缺失时不猜测」原则一致。
Considered options
- 最窄语义(仅节点自身资料变化才更新,结构变化完全不动时间戳):实现最简,但把服务器移入/移出分组、组内重排不会在任何节点留下痕迹,与「分组内容被改过」的用户直觉不符。被否。
- 写入即更新(不比较内容,任何写操作都刷新相关节点):无需比较逻辑,但内容未变的订阅刷新会刷新整棵子树的修改时间,同名重命名与同值保存也会伪造变化,事实失真。被否。
Consequences
- v5 文档中未知的时间戳省略键;
CatalogEntry的Equatable包含时间戳,跨时间构造的目录夹具做整体相等比较时必须用受控时刻。 - 展示 UI 不在本次范围内;后续直接读取节点的创建/修改时间即可,语义以本 ADR 与 GLOSSARY「节点时间戳」为准。