ls1intum / Apollon_standalone

Standalone version of Apollon Editor
MIT License
11 stars 2 forks source link

add support for atomic saves #72

Closed loreanvictor closed 10 months ago

loreanvictor commented 10 months ago

Previously, diagram saves (for example, during realtime collaboration) would follow these steps:

  1. The server would receive a change from a client
  2. The server would load the diagram
  3. The server would apply the changes
  4. The server would save the diagram and broadcast the changes

Since updating diagrams was not atomic, there was a potential for clashes while updating a diagram: for example an update could be initiated by another client while the server is between steps 2 and 4, resulting in corrupted stored data.

This PR changes the process to enable atomic updates, resolving this issue:

  1. The server will receive a change from a client
  2. The server atomically updates the diagram
  3. The server broadcasts the change

The DiagramStorageService interface is updated with two additional methods:

export interface DiagramStorageService {
  saveDiagram(diagramDTO: DiagramDTO, token: string): Promise<string>;
  getDiagramByLink(token: string): Promise<DiagramDTO | undefined>;

  // 👇 these methods are added via this PR
  patchDiagram(token: string, patch: Operation[]): Promise<void>;
  diagramExists(token: string): Promise<boolean>;
}

DiagramFileStorageService provides implementations for both of these methods. It will rate limit calls to saveDiagram() and calls to patchDiagram() in a single queue, as the purpose of the rate limiting is to avoid frequently modifying the diagram files on the filesystem regardless of the nature of the change (i.e. a patch will be overwritten by a following save and vice-versa, so they should be debounced w.r.t. each other).