More fixes

This commit is contained in:
Andras Schmelczer 2026-04-26 13:59:44 +01:00
parent 3d285b0b6e
commit 039affff09
10 changed files with 91 additions and 135 deletions

View file

@ -717,19 +717,23 @@ impl Database {
.await
.context("Failed to commit transaction")?;
// The broadcast is delivered to every connected client except the
// author — the send task filters on `origin_device_id` (see
// `websocket.rs`). The origin already has authoritative state
// from the HTTP response that triggered this write.
self.broadcasts.send_document_update(
vault_id.clone(),
WebSocketServerMessageWithOrigin::with_origin(
version.device_id.clone(),
WebSocketServerMessage::VaultUpdate(WebSocketVaultUpdate {
document: version.clone().into(),
}),
),
);
// For non-delete writes the originating device already has
// authoritative state from its HTTP response, so we tag the
// broadcast with `origin_device_id` and the send task in
// `websocket.rs` filters it out for that device. Deletes are
// delivered to *every* connected client including the author —
// the originator only removes the document from its sync queue
// once it receives this receipt.
let envelope = WebSocketServerMessage::VaultUpdate(WebSocketVaultUpdate {
document: version.clone().into(),
});
let with_origin = if version.is_deleted {
WebSocketServerMessageWithOrigin::new(envelope)
} else {
WebSocketServerMessageWithOrigin::with_origin(version.device_id.clone(), envelope)
};
self.broadcasts
.send_document_update(vault_id.clone(), with_origin);
Ok(())
}

View file

@ -58,11 +58,15 @@ pub struct CursorPositionFromServer {
pub clients: Vec<ClientCursors>,
}
// One committed version, broadcast to every connected client *except*
// the device that authored it — that device already has the new state
// via its HTTP response. The server also emits these one-at-a-time to
// catch up a freshly-connected client on versions committed while it
// was offline, in ascending `vault_update_id` order.
// One committed version. Non-delete updates are broadcast to every
// connected client *except* the device that authored them — that
// device already has the new state via its HTTP response. Deletes are
// broadcast to every client including the author: the author keeps
// the document in its sync queue until this receipt arrives so a late
// remote update can't sneak in between the HTTP response and the
// queue cleanup. The server also emits these one-at-a-time to catch
// up a freshly-connected client on versions committed while it was
// offline, in ascending `vault_update_id` order.
#[derive(TS, Serialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct WebSocketVaultUpdate {

View file

@ -165,6 +165,9 @@ async fn websocket(
Ok(update) => {
// Drop messages this device authored because the HTTP
// response already carried authoritative state back.
// Delete broadcasts are sent without an origin so the
// author also receives them — that's the receipt the
// client needs to drop the doc from its sync queue.
if Some(&device_id) == update.origin_device_id.as_ref() {
continue;
}