When get_changes has to fall back to get_changes_slow it can be very
slow, having to traverse the entire graph but also suffers from having
to keep track of the seen dependencies in a hashset (which rather
thrashes the memory).
Instead, if we calculate the vector clock for each hash we are given and
take the maximum over those then we can see which changes we need more
easily. In the worst case this still suffers from going through the
entire graph but this could be cached for later use. The worst case is
now when an actor makes a single change right at the start of the
history. In this case we have to go through the entire graph just to
find it and ensure that it is in the closure.
The logic for condensing multiple inserts was faulty in that it did not
take into account the `insert` flag on the ops that were being
condensed. This led to an issue where multiple set operations on an
object were converted into a multi-insert operation in the patch. This
commit adds a fix and a few tests.
The javascript implementation of automerge sorts actor IDs
lexicographically when encoding changes. We were sorting actor IDs in
the order the appear in the change we're encoding. This meant that the
index that we assigned to operations in the encoded change was different
to that which the javascript implementation assigns, resulting in
mismatched head errors as the hashes we created did not match the
javascript implementation.
This change fixes the issue by sorting actor IDs lexicographically. We
make a pass over the operations in the change before encoding to collect
the actor IDs and sort them. This means we no longer need to pass a
mutable `Vec<ActorId>` to the various encode functions, which cleans
things up a little.
Fixes#240
This resulted in one failing test which was due to the pending_changes
we report for a patch being incorrectly calculated from missing
dependencies. I've added a test for this failure and fixed it, interop
tests now pass.
The last commit added a `-o` parameter to `automerge export` for
consistency with `automerge merge`. This commit makes it possible to
omit this parameter.
`merge` loads documents either from a list of path, or from standard
input, merges them and emits the merged document to standard output or a
given path.
* Add combined frontend and backend interface
This provides a simpler interface to automerge when one doesn't
particularly need to separate things across multiple threads.
* Use mutationtracker in frontendstate
This allows us to directly track the modified optimistic state and
avoids us having to clone the state when we receive a non-local patch.
* Split mutation tracker from OptimisticStateTree
* Store diffs not whole patches
* Reset the reconciled_root_state when no in_flight_requests
* Document some functions
* Use .. in struct destructuring
* Update docs
* Make some bits more visible
* Add basic proxy with map
* Actually expose the Proxies
* Add more proxies and functionality
* Use &str instead of &SmolStr
* Add some derives
* Add derives to RootProxy
* Add value method
* Add general value method to ValueProxy
* Rename *Proxy to *Ref and update modules
* Format
* Fixup Sequence name
* Use tinyvec for actor id
Most of the time users will not be using their own identifiers and so
use random uuids. These can fit nicely on the stack for a speedup.
TinyVec allows us to capture this mostly stack, sometimes heap
behaviour.
* Use git version of tinyvec for arbitrary