Verify that a continuous changes that has an active late feed serves the expected results if the channel cache associated with the late feed is compacted out of the cache
(t *testing.T)
| 350 | // Verify that a continuous changes that has an active late feed serves the expected results if the |
| 351 | // channel cache associated with the late feed is compacted out of the cache |
| 352 | func TestLateSequenceHandlingDuringCompact(t *testing.T) { |
| 353 | |
| 354 | base.SetUpTestLogging(t, base.LevelInfo, base.KeyChanges, base.KeyCache) |
| 355 | |
| 356 | cacheOptions := shortWaitCache() |
| 357 | cacheOptions.ChannelCacheOptions.MaxNumChannels = 100 |
| 358 | db, ctx := setupTestDBWithCacheOptions(t, cacheOptions) |
| 359 | defer db.Close(ctx) |
| 360 | |
| 361 | caughtUpStart := db.DbStats.CBLReplicationPull().NumPullReplCaughtUp.Value() |
| 362 | |
| 363 | changesCtx, changesCtxCancel := context.WithCancel(ctx) |
| 364 | var changesFeedsWg sync.WaitGroup |
| 365 | var seq1Wg, seq2Wg, seq3Wg sync.WaitGroup |
| 366 | // Start 100 continuous changes feeds |
| 367 | for i := 0; i < 100; i++ { |
| 368 | changesFeedsWg.Add(1) |
| 369 | seq1Wg.Add(1) |
| 370 | seq2Wg.Add(1) |
| 371 | seq3Wg.Add(1) |
| 372 | go func(i int) { |
| 373 | defer changesFeedsWg.Done() |
| 374 | var options ChangesOptions |
| 375 | options.Since = SequenceID{Seq: 0} |
| 376 | options.ChangesCtx = changesCtx |
| 377 | options.Continuous = true |
| 378 | options.Wait = true |
| 379 | channelName := fmt.Sprintf("chan_%d", i) |
| 380 | perRequestDb, err := CreateDatabase(db.DatabaseContext) |
| 381 | dbCollection, ctx := GetSingleDatabaseCollectionWithUser(ctx, t, perRequestDb) |
| 382 | assert.NoError(t, err) |
| 383 | ctx = base.CorrelationIDLogCtx(ctx, fmt.Sprintf("context_%s", channelName)) |
| 384 | feed, err := dbCollection.MultiChangesFeed(ctx, base.SetOf(channelName), options) |
| 385 | require.NoError(t, err, "Feed initialization error") |
| 386 | |
| 387 | // Process feed until closed by terminator in main goroutine |
| 388 | feedCount := 0 |
| 389 | seqArrived := make([]bool, 4) |
| 390 | for event := range feed { |
| 391 | |
| 392 | if event == nil { |
| 393 | continue |
| 394 | } |
| 395 | if event.Seq.Seq == 1 { |
| 396 | seq1Wg.Done() |
| 397 | } else if event.Seq.Seq == 2 { |
| 398 | seq2Wg.Done() |
| 399 | } else if event.Seq.Seq == 3 && seqArrived[3] == false { |
| 400 | // seq 3 may arrive twice for feeds that roll back their low sequence after eviction. Check flag to |
| 401 | // only notify arrival the first time |
| 402 | seq3Wg.Done() |
| 403 | } |
| 404 | seqArrived[event.Seq.Seq] = true |
| 405 | log.Printf("Got feed event for %v: %v", channelName, event) |
| 406 | feedCount++ |
| 407 | } |
| 408 | log.Printf("Feed closed for %s", channelName) |
| 409 | // Feeds that stay resident in the cache will get seqs 1, 3, 2 |
nothing calls this directly
no test coverage detected