集成

Yjs 协作

将 Coaction 自有 pure state 绑定到 Y.Doc,并由 Yjs provider 负责 peer transport。

@coaction/yjs 在 Coaction store pure data 与 Yjs 之间同步。它不提供网络连接;peer transport 应选择 y-websockety-webrtc 或其他 Yjs provider。

Middleware 设置

import { create } from 'coaction';
import { yjs } from '@coaction/yjs';

const store = create(source, {
  middlewares: [yjs()]
});

Middleware 会创建 Y.Doc、绑定 store,并把 cleanup 接到 store.destroy()

使用已有 Y.Doc

import { bindYjs } from '@coaction/yjs';
import { Doc } from 'yjs';
import { WebsocketProvider } from 'y-websocket';

const doc = new Doc();
const provider = new WebsocketProvider(
  'wss://collaboration.example',
  'room-id',
  doc
);

const binding = bindYjs(store, {
  doc,
  key: 'counter'
});

// 稍后
binding.destroy();
provider.destroy();
store.destroy();

bindYjs() 返回 doc、根 mapsyncNow()destroy()

存储与同步模型

  • 状态位于 doc.getMap(key).get('state')
  • 嵌套对象和数组转换为 Y.MapY.Array
  • 本地 Coaction change 与上次同步 snapshot 做 diff;
  • 远端 Yjs update 会 replay 到 Coaction;
  • 方法与 computed getter 不属于同步 payload。

默认 key 为 coaction:${store.name}

冲突语义

对不同字段的并发编辑可以通过 Yjs 合并;同一 scalar field 的冲突遵循 Yjs 语义,对该值可近似理解为 last-writer-wins。需要交换律的操作(如分布式 counter)应使用 CRDT-native Yjs structure 或 operation 建模,而不是不断替换 scalar。

要求与限制

  • 同步状态应保持 plain 且可序列化;
  • Yjs binding 支持 local 与 shared-main,不支持 shared client;
  • 只绑定拥有状态的一端,client mirror 不能建立第二个协作权威;
  • 非常大或频繁变化的 tree 可能产生大量 update traffic;
  • 必须释放旧 binding,避免重复 observer 与 stale write。

远端 snapshot 与 delete 仍遵守 Coaction 固定 schema。未知根 key 被拒绝;exact replacement 缺少已知单 store 字段时,该字段可能变为 undefined

本页目录