automerge/automerge/sync/index.html
2023-03-09 15:11:59 +00:00

64 lines
No EOL
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Sync Protocol"><meta name="keywords" content="rust, rustlang, rust-lang, sync"><title>automerge::sync - Rust</title><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/SourceSerif4-Regular-1f7d512b176f0f72.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/FiraSans-Regular-018c141bf0843ffd.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/FiraSans-Medium-8f9a781e4970d388.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/SourceSerif4-Bold-124a1ca42af929b6.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2"><link rel="stylesheet" href="../../static.files/normalize-76eba96aa4d2e634.css"><link rel="stylesheet" href="../../static.files/rustdoc-93196c7a1c3542a8.css" id="mainThemeStyle"><link rel="stylesheet" id="themeStyle" href="../../static.files/light-4743e13df3dfe8c4.css"><link rel="stylesheet" disabled href="../../static.files/dark-0e1b889528bd466b.css"><link rel="stylesheet" disabled href="../../static.files/ayu-65289d5d067c7c66.css"><script id="default-settings" ></script><script src="../../static.files/storage-d43fa987303ecbbb.js"></script><script defer src="../../static.files/main-3367e395607fafc1.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-13285aec31fa243e.css"></noscript><link rel="icon" href="https:///raw.githubusercontent.com/automerge/automerge-rs/main/img/favicon.ico"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle">&#9776;</button><a class="logo-container" href="../../automerge/index.html"><img src="https://raw.githubusercontent.com/automerge/automerge-rs/main/img/brandmark.svg" alt="logo"></a><h2></h2></nav><nav class="sidebar"><a class="logo-container" href="../../automerge/index.html">
<img src="https://raw.githubusercontent.com/automerge/automerge-rs/main/img/brandmark.svg" alt="logo"></a><h2 class="location"><a href="#">Module sync</a></h2><div class="sidebar-elems"><section><ul class="block"><li><a href="#structs">Structs</a></li><li><a href="#enums">Enums</a></li><li><a href="#traits">Traits</a></li></ul></section></div></nav><main><div class="width-limiter"><nav class="sub"><form class="search-form"><span></span><input class="search-input" name="search" aria-label="Run search in the documentation" autocomplete="off" spellcheck="false" placeholder="Click or press S to search, ? for more options…" type="search"><div id="help-button" title="help" tabindex="-1"><a href="../../help.html">?</a></div><div id="settings-menu" tabindex="-1"><a href="../../settings.html" title="settings"><img width="22" height="22" alt="Change settings" src="../../static.files/wheel-5ec35bf9ca753509.svg"></a></div></form></nav><section id="main-content" class="content"><div class="main-heading"><h1>Module <a href="../index.html">automerge</a>::<wbr><a class="mod" href="#">sync</a><button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"><img src="../../static.files/clipboard-7571035ce49a181d.svg" width="19" height="18" alt="Copy item path"></button></h1><span class="out-of-band"><a class="srclink" href="../../src/automerge/sync.rs.html#1-963">source</a> · <button id="toggle-all-docs" title="collapse all docs">[<span>&#x2212;</span>]</button></span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><h2 id="sync-protocol"><a href="#sync-protocol">Sync Protocol</a></h2>
<p>The sync protocol is based on this paper:
<a href="https://arxiv.org/abs/2012.00472">https://arxiv.org/abs/2012.00472</a>, it assumes a reliable in-order stream
between two peers who are synchronizing a document.</p>
<p>Each peer maintains a <a href="struct.State.html" title="State"><code>State</code></a> for each peer they are synchronizing with.
This state tracks things like what the heads of the other peer are and
whether there are in-flight messages. Anything which implements <a href="trait.SyncDoc.html" title="SyncDoc"><code>SyncDoc</code></a>
can take part in the sync protocol. The flow goes something like this:</p>
<ul>
<li>The initiating peer creates an empty <a href="struct.State.html" title="State"><code>State</code></a> and then calls
<a href="trait.SyncDoc.html#tymethod.generate_sync_message" title="SyncDoc::generate_sync_message"><code>SyncDoc::generate_sync_message</code></a> to generate new sync message and sends
it to the receiving peer.</li>
<li>The receiving peer receives a message from the initiator, creates a new
<a href="struct.State.html" title="State"><code>State</code></a>, and calls <a href="trait.SyncDoc.html#tymethod.receive_sync_message" title="SyncDoc::receive_sync_message"><code>SyncDoc::receive_sync_message</code></a> on its view of the
document</li>
<li>The receiving peer then calls <a href="trait.SyncDoc.html#tymethod.generate_sync_message" title="SyncDoc::generate_sync_message"><code>SyncDoc::generate_sync_message</code></a> to generate
a new sync message and send it back to the initiator</li>
<li>From this point on each peer operates in a loop, receiving a sync message
from the other peer and then generating a new message to send back.</li>
</ul>
<h3 id="example"><a href="#example">Example</a></h3>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>automerge::{transaction::Transactable, sync::{<span class="self">self</span>, SyncDoc}, ReadDoc};
<span class="comment">// Create a document on peer1
</span><span class="kw">let </span><span class="kw-2">mut </span>peer1 = automerge::AutoCommit::new();
peer1.put(automerge::ROOT, <span class="string">&quot;key&quot;</span>, <span class="string">&quot;value&quot;</span>)<span class="question-mark">?</span>;
<span class="comment">// Create a state to track our sync with peer2
</span><span class="kw">let </span><span class="kw-2">mut </span>peer1_state = sync::State::new();
<span class="comment">// Generate the initial message to send to peer2, unwrap for brevity
</span><span class="kw">let </span>message1to2 = peer1.sync().generate_sync_message(<span class="kw-2">&amp;mut </span>peer1_state).unwrap();
<span class="comment">// We receive the message on peer2. We don&#39;t have a document at all yet
// so we create one
</span><span class="kw">let </span><span class="kw-2">mut </span>peer2 = automerge::AutoCommit::new();
<span class="comment">// We don&#39;t have a state for peer1 (it&#39;s a new connection), so we create one
</span><span class="kw">let </span><span class="kw-2">mut </span>peer2_state = sync::State::new();
<span class="comment">// Now receive the message from peer 1
</span>peer2.sync().receive_sync_message(<span class="kw-2">&amp;mut </span>peer2_state, message1to2)<span class="question-mark">?</span>;
<span class="comment">// Now we loop, sending messages from one to two and two to one until
// neither has anything new to send
</span><span class="kw">loop </span>{
<span class="kw">let </span>two_to_one = peer2.sync().generate_sync_message(<span class="kw-2">&amp;mut </span>peer2_state);
<span class="kw">if let </span><span class="prelude-val">Some</span>(message) = two_to_one.as_ref() {
<span class="macro">println!</span>(<span class="string">&quot;two to one&quot;</span>);
peer1.sync().receive_sync_message(<span class="kw-2">&amp;mut </span>peer1_state, message.clone())<span class="question-mark">?</span>;
}
<span class="kw">let </span>one_to_two = peer1.sync().generate_sync_message(<span class="kw-2">&amp;mut </span>peer1_state);
<span class="kw">if let </span><span class="prelude-val">Some</span>(message) = one_to_two.as_ref() {
<span class="macro">println!</span>(<span class="string">&quot;one to two&quot;</span>);
peer2.sync().receive_sync_message(<span class="kw-2">&amp;mut </span>peer2_state, message.clone())<span class="question-mark">?</span>;
}
<span class="kw">if </span>two_to_one.is_none() &amp;&amp; one_to_two.is_none() {
<span class="kw">break</span>;
}
}
<span class="macro">assert_eq!</span>(peer2.get(automerge::ROOT, <span class="string">&quot;key&quot;</span>)<span class="question-mark">?</span>.unwrap().<span class="number">0</span>.to_str(), <span class="prelude-val">Some</span>(<span class="string">&quot;value&quot;</span>));
</code></pre></div>
</div></details><h2 id="structs" class="small-section-header"><a href="#structs">Structs</a></h2><div class="item-table"><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.BloomFilter.html" title="automerge::sync::BloomFilter struct">BloomFilter</a></div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.DecodeBloomError.html" title="automerge::sync::DecodeBloomError struct">DecodeBloomError</a></div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.Have.html" title="automerge::sync::Have struct">Have</a></div><div class="item-right docblock-short">A summary of the changes that the sender of the message already has.
This is implicitly a request to the recipient to send all changes that the
sender does not already have.</div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.Message.html" title="automerge::sync::Message struct">Message</a></div><div class="item-right docblock-short">The sync message to be sent.</div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.State.html" title="automerge::sync::State struct">State</a></div><div class="item-right docblock-short">The state of synchronisation with a peer.</div></div></div><h2 id="enums" class="small-section-header"><a href="#enums">Enums</a></h2><div class="item-table"><div class="item-row"><div class="item-left module-item"><a class="enum" href="enum.DecodeStateError.html" title="automerge::sync::DecodeStateError enum">DecodeStateError</a></div></div><div class="item-row"><div class="item-left module-item"><a class="enum" href="enum.ReadMessageError.html" title="automerge::sync::ReadMessageError enum">ReadMessageError</a></div></div></div><h2 id="traits" class="small-section-header"><a href="#traits">Traits</a></h2><div class="item-table"><div class="item-row"><div class="item-left module-item"><a class="trait" href="trait.SyncDoc.html" title="automerge::sync::SyncDoc trait">SyncDoc</a></div><div class="item-right docblock-short">A document which can take part in the sync protocol</div></div></div></section></div></main><div id="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="automerge" data-themes="" data-resource-suffix="" data-rustdoc-version="1.68.0 (2c8cc3432 2023-03-06)" data-search-js="search-98d53477a794af0b.js" data-settings-js="settings-c3c521c753752a1a.js" data-settings-css="settings-08ddfdda51b8ee2e.css" ></div></body></html>