分布式数据对象断连时,后写覆盖先写只是开始
两台设备协同编辑同一份数据,WiFi 切换、蓝牙断连重连,重连之后两边的 UI 状态对不上。你去查 distributedDataObject 的同步机制,会发现它采用的是最终一致性模型:本地写入立即生效,跨设备同步存在延迟,断连期间两端各自的写入会产生冲突,而系统底层不提供自定义冲突策略的接口,默认行为就是后写覆盖先写。
指望框架自动“对齐”是不现实的。稳定的做法不在框架层,在业务层加四件事:感知链路状态、断连期间冻结写入、用版本号做冲突仲裁、关键数据持久化兜底。
on('status') 是冻结写入的触发点
DDO 提供 on('status'),状态取值包括 online、offline、restored。收到 offline 之后,最危险的不是“同步慢了”,而是本地继续接受写入,制造出断连期间无法仲裁的脏数据。writeFrozen 应该在 offline 时立即置为 true,UI 进入“同步暂停”的降级态,等 restored 之后再解除冻结。
typescript
dataObject.on('status', (state: string) => {
if (state === 'offline') {
this.writeFrozen = true
} else if (state === 'restored') {
this.writeFrozen = false
}
})
版本号让新状态覆盖旧状态
数据模型里带一个单调递增的 version 和 lastEditor。change 回调到达时,只采纳版本号更高的变更,版本号落后的过期数据直接丢弃。这不是“让框架帮你合并”,而是业务层主动规定:谁的版本新,谁说话。
typescript
class CollabData {
version: number = 0
lastEditor: string = ''
content: string = ''
}
dataObject.on('change', (sessionId: string, fields: string[]) => {
if (this.writeFrozen) {
return
}
const remote = dataObject as CollabData
if (remote.version > this.localVersion) {
this.applyRemote(remote)
}
})
纯内存态撑不过进程退出
save() 是必须的。DDO 本身是内存态对象,进程被杀或长时间断连之后,没有落盘的数据不会自己回来。如果这份数据不能丢,持久化兜底不能省,或者从一开始就不要把不可丢的数据完全押在纯内存 DDO 上。版本号负责断连期间的仲裁,持久化负责进程边界之外的存活,两者解决的不是同一个问题。
更多推荐

所有评论(0)