automerge / automerge-repo

MIT License
458 stars 51 forks source link

Fix: Fix race condition in `Repo.flush` method #341

Closed mykola-vrmchk closed 5 months ago

mykola-vrmchk commented 5 months ago

Motivation

The Flush method waits for specific heads to be written on the disk, there was a race condition when you do change exactly after the flush heads on the disk would never be equal to the flushing heads. This snippet shows what exactly was happening in the storage subsystem (and before this PR it would hang forever):

      it.only("Flush should resolve even if doc is getting changed afterwards", async () => {
        const storage = new StorageSubsystem(new NodeFSStorageAdapter())

        const doc = A.change(A.init<any>(), "first change", d => {
          d.foo = "bar"
        })

        // start flushing (with current heads).
        const key = parseAutomergeUrl(generateAutomergeUrl()).documentId
        const flush = storage.flush(key, doc)

        // make a change (changes heads).
        const changedDoc = A.change<any>(doc, "second change", d => {
          d.foo = "baz"
        })
        await storage.saveDoc(key, changedDoc)

        await flush // <- hangs here forever.
      }) 

Fix

Invoke save on flush method, because of how automerge storage works it will not break it, it could just make additional useless write, which is already pending, or save mutations which are already saved.