This commit is contained in:
Andras Schmelczer 2026-09-27 08:29:17 +01:00
commit 3dab48f58b
2 changed files with 1141 additions and 1376 deletions

View file

@ -1,6 +1,6 @@
# Sync algorithm
The current API v5 server stores immutable content versions and a separately
The current API v4 server stores immutable content versions and a separately
versioned file manifest. Clients reconcile snapshots with the current local files. The server does not merge competing edits.
## Identity and ordering
@ -32,14 +32,17 @@ head is retained only until it can be applied. The observed hash records local
presence as well as rename evidence; there are no separate bootstrap or
materialization flags. Scans rebuild physical exclusions. Original server paths
remain saved while excluded, so ignoring a file cannot publish a deletion or
forget a deferred rename. Rejected payloads and messages live on the retained
requests that event replay already needs for uncertain acknowledgements.
forget a deferred rename. A permanently rejected upload pauses the whole sync
loop. Its exact pending request and rejection message remain saved across restarts;
an explicit reset or settings change retries it before reading newer remote state.
There is no separate list of rejected requests or late-receipt matching.
For text, the client compares the common base, current local bytes and current
remote bytes using `reconcile-text`. Configured extensions and valid UTF-8 without
NUL bytes determine whether text merging is allowed. Diffs optimize transport;
they do not authorize the server to merge a stale base. Large diff operation sets
are sent as snapshots.
are sent as snapshots. Snapshots remain bytes plus hashes in memory; only outgoing
wire payloads are encoded as base64.
If only one side changed, that side is retained. Concurrent unmergeable changes
keep the server version. First contact with existing local text has no shared ancestor and uses
@ -98,10 +101,13 @@ WebSocket `vaultChanged` hints wake HTTP replay. The server periodically compare
its history checkpoint to detect missed broadcasts; transport liveness checks
recover disconnected clients. Authentication and permanent errors remain visible;
transient errors retry according to client settings. Observer callback failures
are isolated from the background sync loop.
are isolated from the background sync loop. The WebSocket manager sends its own
handshake before announcing a connection. Shutdown retires its callbacks and
drains existing message handlers without waiting for a close handshake.
API v5 clients and servers must be deployed together. V4 databases migrate without
removing history. CLI and desktop Obsidian share the Node filesystem adapter and
API v4 clients and servers must be deployed together. Only the current client
state and server schema are supported; format changes require fresh state stores.
CLI and desktop Obsidian share the Node filesystem adapter and
complete-record metadata persistence. Node file moves use exclusive creation
followed by unlink, so interruption may leave two ordinary files. Metadata alone
is flushed before an atomic rename; there is no user-file durability protocol.

View file

@ -75,21 +75,13 @@ chmod +x sync_server-linux-x86_64
### Build from Source
Requirements: Rust 1.92.0+, SQLite development headers, SQLx CLI
Requirements: Rust 1.92.0+, SQLite development headers
```bash
# Clone the repository
git clone https://github.com/schmelczer/vault-link.git
cd vault-link/sync-server
# Install SQLx CLI
cargo install sqlx-cli
# Set up the database
sqlx database create --database-url sqlite://db.sqlite3
sqlx migrate run --source src/app_state/database/migrations --database-url sqlite://db.sqlite3
cargo sqlx prepare --workspace
# Build in release mode
cargo build --release