diff --git a/src/ot/client.ts b/src/ot/client.ts index 938d004..def3135 100644 --- a/src/ot/client.ts +++ b/src/ot/client.ts @@ -40,12 +40,27 @@ export class Client { if (revision < 0 || this.revision > revision) { throw new Error("operation revision not in history"); } + if (revision < this.revision) { + return; + } const isSelfOp = operation.id === this.outstanding?.id; + if (this.outstanding) { + // 将outstanding操作转化为执行operation后的操作 + const newOp = TextOperation.transform(this.outstanding, operation); + newOp.id = this.outstanding.id; + this.outstanding = newOp; + } + for (let i = 0; i < this.buffer.length; i++) { // 将buffer中的操作转换为基于服务端文档状态的操作 - const newOp = TextOperation.transform(this.buffer[i], this.buffer[i - 1] || operation); + // FIXME: 对buffer中的操作应该合并后再transform + const newOp = TextOperation.transform( + this.buffer[i], + // 如果有outstanding,buffer[0]应该基于outstanding + this.buffer[i - 1] || this.outstanding || operation + ); newOp.id = this.buffer[i].id; this.buffer[i] = newOp; } @@ -66,7 +81,7 @@ export class Client { if (isSelfOp) { this.serverAck(); } - console.log('mattuy', 'client', this.name, this) + console.log("mattuy", "client", this.name, this); } // 服务端已确认收到发送的操作,从buffer中移除该操作,尝试发送下一个 @@ -88,7 +103,7 @@ export class Client { // 向服务端发送本地待提交的操作,这里没有实现操作压缩,我们一个一个发送 this.outstanding = this.buffer.shift()!; // 模拟向服务端发送操作,实际实现应该通过网络 - server.receiveOperation(this.revision, this.outstanding); + server.receiveOperation(this, this.revision, this.outstanding); // 应该有超时重发机制,这里没有实现 } diff --git a/src/ot/server.ts b/src/ot/server.ts index 0e4cbf0..cbafc6e 100644 --- a/src/ot/server.ts +++ b/src/ot/server.ts @@ -16,7 +16,7 @@ class Server { } // 每当从客户端接收到操作时调用此方法 - async receiveOperation(revision: number, operation: TextOperation) { + async receiveOperation(client: Client, revision: number, operation: TextOperation) { if (revision < 0 || this.operations.length < revision) { throw new Error("operation revision not in history"); } @@ -31,6 +31,8 @@ class Server { // op' = transform(op, op1) // op基于 revision+i 版本的文档操作,op'基于 revision+i+1 版本的文档操作 operation = transform(operation, concurrentOperations[i]); + // 向客户端发送其它客户端的操作 + client.applyServer(revision + i + 1, concurrentOperations[i]); } operation.id = opId;