derbyjs / racer

Realtime model synchronization engine for Node.js
1.18k stars 116 forks source link

Fix deferred unload (see a320772a) when unfetching then synchronously subscribing #279

Closed ericyhwang closed 4 years ago

ericyhwang commented 4 years ago

When a doc gets unfetched, https://github.com/derbyjs/racer/pull/276 adds a Share Doc whenNothingPending listener to unload the doc later, instead of doing nothing, which was the cause of a memory leak introduced in https://github.com/derbyjs/racer/pull/266.

However, Racer keeps reference counts itself for fetches and subscriptions, so an immediate subscribe on the same Racer doc does not affect the Share doc at all, which means the doc would still get unloaded, erroneously.

This fix instead retries the Racer _maybeUnloadDoc in that scenario, instead of doing an immediate unload. That guards against Racer getting new doc references while the Share Doc whenNotingPending is in progress.


For reference, the new test for the scenario fails like this without the subscriptions.js change:

  1) loading
       unfetch deferred unload
         does not unload doc if a subscribe is issued in the meantime:
     Uncaught Error: expected undefined to sort of equal { id: 'green', hex: '00ee00' }
      at Assertion.assert (node_modules/expect.js/index.js:96:13)
      at Assertion.eql (node_modules/expect.js/index.js:230:10)
      at .../derbyjs/racer/test/Model/loading.js:93:48
      at process._tickCallback (internal/process/next_tick.js:61:11)