How _changes works - adamcfraser/cbnotes GitHub Wiki

Non-continuous case

  • Request comes in with a since value
  • Gets the set of channels associated with the user making the request. For each channel, calls the channel cache to get an ordered list of sequences since since. The Channel cache will run a view query if needed.
  • Works the ordered channel lists to serve revisions in sequence, and avoid duplicates.
  • Sends last_seq, which is just the sequence of the last revision that was sent.

Continuous case

  • Basically runs a loop that does the equivalent of the non-continuous case in each iteration. The first run of the loop is the same as the non-continuous case. Subsequent iterations set since=lastSeq from the previous iteration.
  • The loop pauses after each iteration waiting for notification that new updates have come through on the feed. Notifications are managed by the Change cache (which works the feed).

In more detail

There are some nuances to the way the changes feed works the channel caches. In each iteration of the changes loop, it creates a feed for each channel cache it has visibility to. This call (to changesFeed()) returns a buffered go-channel (size 1) of revisions, and starts a go routine writing to that go-channel from the channel changes.

The changes feed then works those buffered go-channels in parallel. I'm not how significant the performance benefit we get from the use of buffered go-channels here - the read from the cache is blocking (db.changeCache.GetChangesInChannel), so the only parallel processing is iterating through the returned LogEntry values and converting to ChangeEntry.