Feed to process late sequences for the channel. Updates lastSequence as it works the feed. Error indicates previous position in late sequence feed isn't available, and caller should reset to low sequence.
(ctx context.Context, feedHandler *lateSequenceFeed, singleChannelCache SingleChannelCache, versionType ChangesVersionType)
| 1278 | // Feed to process late sequences for the channel. Updates lastSequence as it works the feed. Error indicates |
| 1279 | // previous position in late sequence feed isn't available, and caller should reset to low sequence. |
| 1280 | func (db *DatabaseCollectionWithUser) getLateFeed(ctx context.Context, feedHandler *lateSequenceFeed, singleChannelCache SingleChannelCache, versionType ChangesVersionType) (<-chan *ChangeEntry, error) { |
| 1281 | |
| 1282 | if !singleChannelCache.SupportsLateFeed() { |
| 1283 | return nil, errors.New("Cache doesn't support late feeds") |
| 1284 | } |
| 1285 | // If the associated cache instance for this feedHandler doesn't match SingleChannelCache, it means the channel cache |
| 1286 | // has been evicted/recreated, and the current feedHandler is no longer valid |
| 1287 | if feedHandler.lateSequenceUUID != singleChannelCache.LateSequenceUUID() { |
| 1288 | return nil, errors.New("Cache/handler mismatch") |
| 1289 | } |
| 1290 | |
| 1291 | // Use LogPriorityQueue for late entries, to utilize the existing Len/Less/Swap methods on LogPriorityQueue for sort |
| 1292 | var logs LogPriorityQueue |
| 1293 | logs, lastSequence, err := singleChannelCache.GetLateSequencesSince(feedHandler.lastSequence) |
| 1294 | if err != nil { |
| 1295 | return nil, err |
| 1296 | } |
| 1297 | if logs == nil || len(logs) == 0 { |
| 1298 | // There are no late entries newer than lastSequence |
| 1299 | feed := make(chan *ChangeEntry) |
| 1300 | close(feed) |
| 1301 | return feed, nil |
| 1302 | } |
| 1303 | |
| 1304 | // Sort late sequences, to ensure duplicates aren't sent in a single continuous _changes iteration when multiple |
| 1305 | // channels have late arrivals |
| 1306 | sort.Sort(logs) |
| 1307 | |
| 1308 | feed := make(chan *ChangeEntry, 1) |
| 1309 | go func() { |
| 1310 | defer close(feed) |
| 1311 | // Write each log entry to the 'feed' channel in turn: |
| 1312 | for _, logEntry := range logs { |
| 1313 | // We don't need TriggeredBy handling here, because when backfilling from a |
| 1314 | // channel in response to a user being added to the channel, we don't need to worry about |
| 1315 | // late arrived sequences |
| 1316 | seqID := SequenceID{ |
| 1317 | Seq: logEntry.Sequence, |
| 1318 | } |
| 1319 | change := makeChangeEntry(ctx, logEntry, seqID, singleChannelCache.ChannelID(), versionType) |
| 1320 | select { |
| 1321 | case <-ctx.Done(): |
| 1322 | return |
| 1323 | |
| 1324 | case feed <- &change: |
| 1325 | } |
| 1326 | } |
| 1327 | }() |
| 1328 | |
| 1329 | feedHandler.lastSequence = lastSequence |
| 1330 | return feed, nil |
| 1331 | } |
| 1332 | |
| 1333 | // Closes a single late sequence feed. |
| 1334 | func (db *DatabaseCollectionWithUser) closeLateFeed(ctx context.Context, feedHandler *lateSequenceFeed) { |
no test coverage detected