TestVariableRateAllocators simulates the following scenario: - import nodes have high sequence allocation rate - client-facing nodes have low sequence allocation rate - documents are imported, then the same documents are immediately updated by clients (including sequence validation triggering nextSe
(t *testing.T)
| 765 | // |
| 766 | // Ensures we don't release more sequences than would be expected based on allocator batch size |
| 767 | func TestVariableRateAllocators(t *testing.T) { |
| 768 | ctx := base.TestCtx(t) |
| 769 | bucket := base.GetTestBucket(t) |
| 770 | defer bucket.Close(ctx) |
| 771 | var expectedAllocations uint64 |
| 772 | |
| 773 | dataStore := bucket.GetSingleDataStore() |
| 774 | stats, err := base.NewSyncGatewayStats() |
| 775 | require.NoError(t, err) |
| 776 | |
| 777 | importStats, err := stats.NewDBStats("import", false, false, false, nil, nil) |
| 778 | require.NoError(t, err) |
| 779 | |
| 780 | importFeedAllocator, err := newSequenceAllocator(ctx, dataStore, importStats.DatabaseStats, base.DefaultMetadataKeys) |
| 781 | require.NoError(t, err) |
| 782 | |
| 783 | // All test allocators are stopped when allocatorCtx is closed |
| 784 | allocatorCtx, cancelFunc := context.WithCancel(ctx) |
| 785 | |
| 786 | // Start import node allocator, performing 10000 allocations/second. |
| 787 | var allocatorWg sync.WaitGroup |
| 788 | allocatorWg.Add(1) |
| 789 | go func() { |
| 790 | count := runAllocator(allocatorCtx, importFeedAllocator, 100*time.Microsecond) // 10000 writes/second |
| 791 | atomic.AddUint64(&expectedAllocations, count) |
| 792 | allocatorWg.Done() |
| 793 | }() |
| 794 | |
| 795 | // Start multiple client node allocators, performing 100 allocations/second |
| 796 | clientAllocators := make([]*sequenceAllocator, 0) |
| 797 | clientAllocatorCount := 10 |
| 798 | for i := 0; i <= clientAllocatorCount; i++ { |
| 799 | clientStats, err := stats.NewDBStats(fmt.Sprintf("client%d", i), false, false, false, nil, nil) |
| 800 | require.NoError(t, err) |
| 801 | clientAllocator, err := newSequenceAllocator(ctx, dataStore, clientStats.DatabaseStats, base.DefaultMetadataKeys) |
| 802 | require.NoError(t, err) |
| 803 | clientAllocators = append(clientAllocators, clientAllocator) |
| 804 | allocatorWg.Add(1) |
| 805 | go func() { |
| 806 | count := runAllocator(allocatorCtx, clientAllocator, 10*time.Millisecond) // 100 writes/second |
| 807 | atomic.AddUint64(&expectedAllocations, count) |
| 808 | allocatorWg.Done() |
| 809 | }() |
| 810 | } |
| 811 | |
| 812 | // Wait for allocators to get up to maximum batch size |
| 813 | time.Sleep(500 * time.Millisecond) |
| 814 | documentCount := 10 |
| 815 | var updateWg sync.WaitGroup |
| 816 | updateWg.Add(documentCount) |
| 817 | for i := 0; i < documentCount; i++ { |
| 818 | go func() { |
| 819 | _ = multiNodeUpdate(t, ctx, importFeedAllocator, clientAllocators, 5, 10*time.Millisecond) |
| 820 | updateWg.Done() |
| 821 | atomic.AddUint64(&expectedAllocations, 6) |
| 822 | }() |
| 823 | } |
| 824 |
nothing calls this directly
no test coverage detected