(t *testing.T)
| 2685 | } |
| 2686 | |
| 2687 | func TestRecentSequenceHandlingForSkippedSequences(t *testing.T) { |
| 2688 | if !base.TestUseXattrs() { |
| 2689 | t.Skip("This test requires xattrs because it writes directly to the xattr") |
| 2690 | } |
| 2691 | defer SuspendSequenceBatching()() // turn off sequence batching to avoid unused sequence(s) being released |
| 2692 | |
| 2693 | base.SetUpTestLogging(t, base.LevelDebug, base.KeyCache, base.KeyChanges) |
| 2694 | |
| 2695 | opts := DefaultCacheOptions() |
| 2696 | opts.CachePendingSeqMaxNum = 1 |
| 2697 | opts.CachePendingSeqMaxWait = 10 * time.Nanosecond |
| 2698 | db, ctx := setupTestDBWithCacheOptions(t, opts) |
| 2699 | defer db.Close(ctx) |
| 2700 | collection, ctx := GetSingleDatabaseCollectionWithUser(ctx, t, db) |
| 2701 | docID := t.Name() + "_doc1" |
| 2702 | docID2 := t.Name() + "_doc2" |
| 2703 | |
| 2704 | // add a couple of docs and wait for them to be cached |
| 2705 | body := Body{"val": "one"} |
| 2706 | _, _, err := collection.Put(ctx, docID, body) |
| 2707 | require.NoError(t, err) |
| 2708 | _, _, err = collection.Put(ctx, docID2, body) |
| 2709 | require.NoError(t, err) |
| 2710 | err = db.changeCache.waitForSequence(ctx, 2, base.DefaultWaitForSequence) |
| 2711 | require.NoError(t, err) |
| 2712 | |
| 2713 | // grab doc and alter sync data of one to artificially create gap in sequences at cache |
| 2714 | xattrs, cas, err := collection.dataStore.GetXattrs(ctx, docID, []string{base.SyncXattrName}) |
| 2715 | require.NoError(t, err) |
| 2716 | var retrievedXattr map[string]interface{} |
| 2717 | require.NoError(t, base.JSONUnmarshal(xattrs[base.SyncXattrName], &retrievedXattr)) |
| 2718 | retrievedXattr["sequence"] = uint64(6) |
| 2719 | retrievedXattr["recent_sequences"] = []uint64{1, 6} |
| 2720 | newXattrVal := map[string][]byte{ |
| 2721 | base.SyncXattrName: base.MustJSONMarshal(t, retrievedXattr), |
| 2722 | } |
| 2723 | _, err = collection.dataStore.UpdateXattrs(ctx, docID, 0, cas, newXattrVal, nil) |
| 2724 | require.NoError(t, err) |
| 2725 | |
| 2726 | // assert that sequence 6 is seen over caching feed |
| 2727 | err = db.changeCache.waitForSequence(ctx, 6, base.DefaultWaitForSequence) |
| 2728 | require.NoError(t, err) |
| 2729 | // assert that skipped is filled + stable sequence and high sequence is as expected |
| 2730 | require.NoError(t, db.changeCache.InsertPendingEntries(ctx)) // empty pending |
| 2731 | db.UpdateCalculatedStats(ctx) |
| 2732 | assert.Equal(t, int64(3), db.DbStats.Cache().NumCurrentSeqsSkipped.Value()) |
| 2733 | assert.Equal(t, int64(0), db.DbStats.Cache().PendingSeqLen.Value()) |
| 2734 | assert.Equal(t, int64(6), db.DbStats.Cache().HighSeqCached.Value()) |
| 2735 | assert.Equal(t, int64(2), db.DbStats.Cache().HighSeqStable.Value()) |
| 2736 | assert.Equal(t, uint64(7), db.changeCache.getNextSequence()) |
| 2737 | |
| 2738 | // alter sync data on doc2 to create recent sequence history to plug gap in sequences that have been pushed to skipped |
| 2739 | xattrs, cas, err = collection.dataStore.GetXattrs(ctx, docID2, []string{base.SyncXattrName}) |
| 2740 | require.NoError(t, err) |
| 2741 | retrievedXattr = map[string]interface{}{} |
| 2742 | require.NoError(t, base.JSONUnmarshal(xattrs[base.SyncXattrName], &retrievedXattr)) |
| 2743 | retrievedXattr["sequence"] = uint64(5) |
| 2744 | retrievedXattr["recent_sequences"] = []uint64{2, 3, 4, 5} |
nothing calls this directly
no test coverage detected