Last active
August 17, 2021 15:18
-
-
Save dan-weaver/9d2839e0ed12a03be74724c5c61198a3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Create two peers, each with one Automerge doc | |
peer2's doc is a clone of peer1's to ensure common history | |
Each peer has a syncState representing the estimated state of the other peer | |
Each peer has a FIFO list "inbox" emulating a network transport | |
Every 500ms, simulate the network for each peer in turn, via update(): | |
- check for any messages in the peer's inbox | |
- call Automerge.receiveSyncMessage for each message | |
- and update doc & sync accordingly | |
- then clear the inbox | |
- check whether we think we need to send sync message to peer via generateSyncMessage *** | |
- update sync accordingly (??) | |
- if there was a message, push it into the peer's inbox for the next update() | |
*** Why does it continue to think there are sync updates required, | |
even though both docs are already in sync? | |
Notes: | |
it doesn't matter whether we poll peer1 first or peer2, the same thing happens | |
*/ | |
import Automerge from "https://cdn.skypack.dev/[email protected]"; | |
let peer1 = { | |
name: "peer1", | |
doc: Automerge.init(), | |
sync: Automerge.initSyncState(), // for syncing to peer2 | |
inbox: [] // FIFO for simulated network transport | |
}; | |
let peer2 = { | |
name: "peer2", | |
// peer2's doc is a duplicate of peer1's doc: | |
doc: Automerge.clone(peer1.doc), | |
sync: Automerge.initSyncState(), // for syncing to peer1 | |
inbox: [] // FIFO for simulated network transport | |
}; | |
// check if a peer has changes to send to the other peer | |
// and if so, post them in the other's inbox | |
function send(self, other) { | |
// do we have any changes (or requests) for the other peer? | |
let [newsync, msg] = Automerge.generateSyncMessage(self.doc, self.sync); | |
self.sync = newsync; | |
// if we have a message to send: | |
if (msg) { | |
// always peer2 | |
// console.log('peer sending', self.name) | |
// send msg to peer by appending to peer's inbox | |
other.inbox.push(msg); | |
// log that we sent a message: | |
document.getElementById("log").innerText += | |
"\n" + | |
"send " + | |
self.name + | |
"->" + | |
other.name + | |
" msg: " + | |
msg.toString(); | |
} | |
} | |
// check if a peer has any messages in its inbox, | |
// and apply them if it does | |
// then clear the inbox | |
function receive(self, other) { | |
// for each message received from the other peer: | |
for (const msg of self.inbox) { | |
// always peer1 | |
// console.log("peer receiving", self.name) | |
// log that we received a message | |
document.getElementById("log").innerText += | |
"\n" + | |
"recv " + | |
self.name + | |
"<-" + | |
other.name + | |
" msg: " + | |
msg.toString(); | |
// apply the change & update our doc & syncState: | |
const [doc, newsync, patch] = Automerge.receiveSyncMessage( | |
self.doc, | |
self.sync, | |
msg | |
); | |
self.doc = doc; | |
self.sync = newsync; | |
send(self, other) | |
} | |
// clear inbox: | |
self.inbox = []; | |
} | |
// both peers initiate a sync | |
send(peer1, peer2); | |
send(peer2,peer1); | |
// simulate network activity | |
function update(self, other) { | |
receive(self, other); | |
} | |
setInterval(function () { | |
// simulate network activity for both peers | |
// doesn't matter which order you do these, same result | |
update(peer2, peer1); | |
update(peer1, peer2); | |
// show current state of docs | |
document.getElementById("result").innerText = | |
"peer1.doc = " + | |
JSON.stringify(peer1.doc) + | |
"\npeer2.doc = " + | |
JSON.stringify(peer2.doc); | |
// show current sync states: | |
document.getElementById("result").innerText += | |
"\npeer1.sync = " + | |
JSON.stringify(peer1.sync, null, " ") + | |
"\npeer2.sync = " + | |
JSON.stringify(peer2.sync, null, " "); | |
// verify that the two peers' docs have different actorIDs: | |
document.getElementById("result").innerText += | |
"\npeer1-actor: " + Automerge.getActorId(peer1.doc); | |
document.getElementById("result").innerText += | |
"\npeer2-actor: " + Automerge.getActorId(peer2.doc); | |
}, 500); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment