mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-11-04 12:54:23 +01:00 
			
		
		
		
	Testing concurrent remote updates (wip)
This commit is contained in:
		@@ -3878,6 +3878,7 @@ class App extends React.Component<AppProps, AppState> {
 | 
			
		||||
      // flush all incoming updates immediately, so that they couldn't be batched with other updates, having different `storeAction`
 | 
			
		||||
      flushSync(() => {
 | 
			
		||||
        const { elements, appState, collaborators, storeAction } = sceneData;
 | 
			
		||||
 | 
			
		||||
        const nextElements = elements
 | 
			
		||||
          ? syncInvalidIndices(elements)
 | 
			
		||||
          : undefined;
 | 
			
		||||
@@ -3892,8 +3893,8 @@ class App extends React.Component<AppProps, AppState> {
 | 
			
		||||
 | 
			
		||||
          const nextCommittedElements = elements
 | 
			
		||||
            ? this.store.filterUncomittedElements(
 | 
			
		||||
                this.scene.getElementsMapIncludingDeleted(), // Only used to detect uncomitted local elements
 | 
			
		||||
                arrayToMap(nextElements ?? []), // We expect all (already reconciled) elements
 | 
			
		||||
                this.scene.getElementsMapIncludingDeleted(), // only used to detect uncomitted local elements
 | 
			
		||||
                arrayToMap(nextElements ?? []), // we expect all (already reconciled) elements
 | 
			
		||||
              )
 | 
			
		||||
            : prevCommittedElements;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -224,6 +224,8 @@ export class Store {
 | 
			
		||||
    const increment = new EphemeralStoreIncrement(change);
 | 
			
		||||
 | 
			
		||||
    // Notify listeners with the increment
 | 
			
		||||
    // CFDO: consider having this async instead, possibly should also happen after the component updates;
 | 
			
		||||
    // or get rid of filtering local in progress elements, switch to unidirectional store flow and keep it synchronous
 | 
			
		||||
    this.onStoreIncrementEmitter.trigger(increment);
 | 
			
		||||
 | 
			
		||||
    return nextSnapshot;
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ import type { ExcalidrawElement, SceneElementsMap } from "../element/types";
 | 
			
		||||
import type { CLIENT_MESSAGE_RAW, SERVER_DELTA, CHANGE } from "./protocol";
 | 
			
		||||
import { debounce } from "../utils";
 | 
			
		||||
import { randomId } from "../random";
 | 
			
		||||
import { orderByFractionalIndex } from "../fractionalIndex";
 | 
			
		||||
 | 
			
		||||
class SocketMessage implements CLIENT_MESSAGE_RAW {
 | 
			
		||||
  constructor(
 | 
			
		||||
@@ -388,13 +389,18 @@ export class SyncClient {
 | 
			
		||||
          !existingElement || // new element
 | 
			
		||||
          existingElement.version < relayedElement.version // updated element
 | 
			
		||||
        ) {
 | 
			
		||||
          // CFDO: in theory could make the yet unsynced element (due to a bug) to move to the top
 | 
			
		||||
          nextElements.set(id, relayedElement);
 | 
			
		||||
          this.relayedElementsVersionsCache.set(id, relayedElement.version);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const orderedElements = orderByFractionalIndex(
 | 
			
		||||
        Array.from(nextElements.values()),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      this.api.updateScene({
 | 
			
		||||
        elements: Array.from(nextElements.values()),
 | 
			
		||||
        elements: orderedElements,
 | 
			
		||||
        storeAction: StoreAction.UPDATE,
 | 
			
		||||
      });
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
@@ -468,9 +474,13 @@ export class SyncClient {
 | 
			
		||||
        prevSnapshot = this.api.store.snapshot;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const orderedElements = orderByFractionalIndex(
 | 
			
		||||
        Array.from(nextElements.values()),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      // CFDO: might need to restore first due to potentially stale delta versions
 | 
			
		||||
      this.api.updateScene({
 | 
			
		||||
        elements: Array.from(nextElements.values()),
 | 
			
		||||
        elements: orderedElements,
 | 
			
		||||
        // even though the snapshot should be up-to-date already,
 | 
			
		||||
        // still some more updates might be triggered,
 | 
			
		||||
        // i.e. as a result from syncing invalid indices
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user