redux-scuttlebutt icon indicating copy to clipboard operation
redux-scuttlebutt copied to clipboard

Action log compaction

Open grrowl opened this issue 7 years ago • 0 comments

Currently redux-scuttlebutt remembers all actions that have ever been dispatched, ever. This is not feasible with long-running applications which dispatch many actions. We should emit a @@scuttlebutt/COMPACTION action occasionally[1] which would give reducers the chance to cull actions no longer required. This action will be emitted locally, and removing an action from the log will prevent it being emitted to new or outdated peers.

  • In the game of life example we can safely forget about any actions which occur before the "RESET" action. It effectively moves the event horizon for all clients to when the RESET action occurred.
  • If you moved objects, any new MOVE_TO(x, y) action effectively overwrites the state affected by any preceding actions for that object.
  • Want to be careful of "compacting" mucking up determinism — for the MOVE_TO example, where Client A controls Object A and Client B controls Object B:
    • For the MOVE_TO example: object A and object B must be able to both MOVE_TO the same location. The existence of A at [1, 1] mustn't change the behaviour of B moving to [1, 1]
    • This is because if there is lag, and we compact B's MOVE_TO actions previous to his [1, 1] movement, we won't know where he was.
    • You can have B simply not update to [1, 1] if A is already there, but you won't be able to use compaction on this action, since the state is dependent on more than just the latest MOVE_TO action.[2]

In regards to the actual dispatching of the @@scuttlebutt/COMPACTION action:

  • We'll probably regularly dispatch to the regular reducers but the state will be the internal scuttlebutt state (an array of the array [ACTION, TIMESTAMP, SOURCE, SNAPSHOT]). The reducer itself can recurse through this array and decide what actions to remove and return the new history.
    • I don't think this will work, though, since nested reducers only return nested parts of state. Multiple reducers can't return conflicting versions of history.
  • Originally this was implemented as a Array.filter() callback, but it was terribly unperformant
    • on every dispatch, we filtered the entire action log, and sometimes those filter callbacks needed to seek forward in history to determine whether the current action should be filtered.

  • [1]: How occasionally? When the log hits a pre-defined limit? Every n actions? In response to specified actions?
  • [2]: This is the most important part and could be explained more succinctly.

grrowl avatar Jan 18 '17 10:01 grrowl