This commit is contained in:
Andras Schmelczer 2026-04-21 20:01:28 +01:00
parent 5ec523234b
commit 9183f30b5d
14 changed files with 86 additions and 16 deletions

View file

@ -0,0 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Like [`DocumentVersion`] but without the `relative_path`.
* Used only in create/update responses when the server had to merge the
* client's content with a newer remote version and therefore must echo
* the merged content back.
*/
export type DocumentUpdateMergedContent = { vaultUpdateId: number, documentId: string, updatedDate: string, contentBase64: string, isDeleted: boolean, userId: string, deviceId: string, };

View file

@ -0,0 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Like [`DocumentVersionWithoutContent`] but without the `relative_path`.
* Used only in create/update responses where the client already tracks
* the path locally (the server is the source of truth for the
* document identity, not its path).
*/
export type DocumentUpdateMetadata = { vaultUpdateId: number, documentId: string, updatedDate: string, isDeleted: boolean, userId: string, deviceId: string, contentSize: number, };

View file

@ -1,8 +1,12 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DocumentVersion } from "./DocumentVersion";
import type { DocumentVersionWithoutContent } from "./DocumentVersionWithoutContent";
import type { DocumentUpdateMergedContent } from "./DocumentUpdateMergedContent";
import type { DocumentUpdateMetadata } from "./DocumentUpdateMetadata";
/**
* Response to an update document request.
* Response to a create/update document request.
*
* Neither variant contains `relative_path`: the client tracks the document's
* on-disk path locally and the server is the authority on document identity
* (`document_id`), not on its path.
*/
export type DocumentUpdateResponse = { "type": "FastForwardUpdate" } & DocumentVersionWithoutContent | { "type": "MergingUpdate" } & DocumentVersion;
export type DocumentUpdateResponse = { "type": "FastForwardUpdate" } & DocumentUpdateMetadata | { "type": "MergingUpdate" } & DocumentUpdateMergedContent;

View file

@ -1,5 +1,6 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { CursorPositionFromServer } from "./CursorPositionFromServer";
import type { WebSocketVaultPathChange } from "./WebSocketVaultPathChange";
import type { WebSocketVaultUpdate } from "./WebSocketVaultUpdate";
export type WebSocketServerMessage = { "type": "vaultUpdate" } & WebSocketVaultUpdate | { "type": "cursorPositions" } & CursorPositionFromServer;
export type WebSocketServerMessage = { "type": "vaultUpdate" } & WebSocketVaultUpdate | { "type": "pathChange" } & WebSocketVaultPathChange | { "type": "cursorPositions" } & CursorPositionFromServer;

View file

@ -0,0 +1,12 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* A rename notification. Emitted whenever a write commits a document at
* a path that differs from what the origin client sent and/or from the
* document's previous stored path. Unlike [`WebSocketVaultUpdate`] this
* event is delivered to all subscribers *including the origin device*,
* because the create/update HTTP response no longer carries the path and
* the origin needs this event to learn the server-canonical path
* (e.g. when the server deduped or rejected a rename).
*/
export type WebSocketVaultPathChange = { vaultUpdateId: number, documentId: string, relativePath: string, };

View file

@ -0,0 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Like [`DocumentVersion`] but without the `relative_path`.
* Used only in create/update responses when the server had to merge the
* client's content with a newer remote version and therefore must echo
* the merged content back.
*/
export interface DocumentUpdateMergedContent { vaultUpdateId: number, documentId: string, updatedDate: string, contentBase64: string, isDeleted: boolean, userId: string, deviceId: string, }

View file

@ -0,0 +1,9 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Like [`DocumentVersionWithoutContent`] but without the `relative_path`.
* Used only in create/update responses where the client already tracks
* the path locally (the server is the source of truth for the
* document identity, not its path).
*/
export interface DocumentUpdateMetadata { vaultUpdateId: number, documentId: string, updatedDate: string, isDeleted: boolean, userId: string, deviceId: string, contentSize: number, }

View file

@ -1,8 +1,12 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DocumentVersion } from "./DocumentVersion";
import type { DocumentVersionWithoutContent } from "./DocumentVersionWithoutContent";
import type { DocumentUpdateMergedContent } from "./DocumentUpdateMergedContent";
import type { DocumentUpdateMetadata } from "./DocumentUpdateMetadata";
/**
* Response to an update document request.
* Response to a create/update document request.
*
* Neither variant contains `relative_path`: the client tracks the document's
* on-disk path locally and the server is the authority on document identity
* (`document_id`), not on its path.
*/
export type DocumentUpdateResponse = { "type": "FastForwardUpdate" } & DocumentVersionWithoutContent | { "type": "MergingUpdate" } & DocumentVersion;
export type DocumentUpdateResponse = { "type": "FastForwardUpdate" } & DocumentUpdateMetadata | { "type": "MergingUpdate" } & DocumentUpdateMergedContent;

View file

@ -1,5 +1,6 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { CursorPositionFromServer } from "./CursorPositionFromServer";
import type { WebSocketVaultPathChange } from "./WebSocketVaultPathChange";
import type { WebSocketVaultUpdate } from "./WebSocketVaultUpdate";
export type WebSocketServerMessage = { "type": "vaultUpdate" } & WebSocketVaultUpdate | { "type": "cursorPositions" } & CursorPositionFromServer;
export type WebSocketServerMessage = { "type": "vaultUpdate" } & WebSocketVaultUpdate | { "type": "pathChange" } & WebSocketVaultPathChange | { "type": "cursorPositions" } & CursorPositionFromServer;

View file

@ -0,0 +1,12 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* A rename notification. Emitted whenever a write commits a document at
* a path that differs from what the origin client sent and/or from the
* document's previous stored path. Unlike [`WebSocketVaultUpdate`] this
* event is delivered to all subscribers *including the origin device*,
* because the create/update HTTP response no longer carries the path and
* the origin needs this event to learn the server-canonical path
* (e.g. when the server deduped or rejected a rename).
*/
export interface WebSocketVaultPathChange { vaultUpdateId: number, documentId: string, relativePath: string, }

View file

@ -283,7 +283,7 @@ export class WebSocketManager {
if (message.type === "vaultUpdate") {
await this.onRemoteVaultUpdateReceived.triggerAsync(message);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
} else if (message.type === "cursorPositions") {
this.logger.debug(
`Received cursor positions for ${JSON.stringify(message.clients)}`

View file

@ -45,7 +45,7 @@ export async function scheduleOfflineChanges(
const allDocuments = new Map(queue.allSettledDocuments());
const locallyRenamedPaths = enqueueRenamedDocuments(deps, allDocuments);
let deletedCandidates = await findLocallyDeletedFiles(operations, allDocuments);
const deletedCandidates = await findLocallyDeletedFiles(operations, allDocuments);
const instructions = await buildSyncInstructions(
deps,

View file

@ -197,7 +197,7 @@ export class SyncEventQueue {
e.documentId === docId) ||
(e.type === SyncEventType.SyncRemote &&
// we care about the local path not the remote
this.getDocumentByDocumentId(e.remoteVersion.documentId as DocumentId)?.path === path)
this.getDocumentByDocumentId(e.remoteVersion.documentId)?.path === path)
);
}

View file

@ -199,9 +199,9 @@ export class Syncer {
private async internalScheduleSyncForOfflineChanges(): Promise<void> {
await scheduleOfflineChanges(
{ logger: this.logger, operations: this.operations, queue: this.queue },
(path) => this.syncLocallyCreatedFile(path),
(args) => this.syncLocallyUpdatedFile(args),
(path) => this.syncLocallyDeletedFile(path),
(path) => { this.syncLocallyCreatedFile(path); },
(args) => { this.syncLocallyUpdatedFile(args); },
(path) => { this.syncLocallyDeletedFile(path); },
);
await this.scheduleDrain();