Skip to content

Commit 10d0928

Browse files
committed
fix: count only the blocks whose purge succeeded
1 parent cb32926 commit 10d0928

2 files changed

Lines changed: 47 additions & 1 deletion

File tree

pkg/pruner/pruner.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ func (p *Pruner) runEventQueuePrune(ctx context.Context, q *EventQueue) error {
259259
func (p *Pruner) purgeFromDrainResult(ctx context.Context, q *EventQueue, result *DrainResult) error {
260260
startTime := time.Now()
261261
totalSubmitted := int64(0)
262+
blocksPruned := int64(0)
262263

263264
// Dependents before blocks, so a block is never removed ahead of the documents that
264265
// reference it.
@@ -277,6 +278,9 @@ func (p *Pruner) purgeFromDrainResult(ctx context.Context, q *EventQueue, result
277278
// A failed collection is re-queued and purged again later, so counting its
278279
// partial progress here would count those documents twice.
279280
totalSubmitted += submitted
281+
if colName == p.collections.BlockCollection {
282+
blocksPruned = int64(result.BlockCount)
283+
}
280284
continue
281285
}
282286

@@ -299,7 +303,9 @@ func (p *Pruner) purgeFromDrainResult(ctx context.Context, q *EventQueue, result
299303
totalSubmitted, result.BlockCount, time.Since(startTime))
300304

301305
p.mu.Lock()
302-
p.totalBlocksPruned += int64(result.BlockCount)
306+
// Only blocks whose own purge succeeded. A re-queued block collection is drained and
307+
// counted again on a later cycle, so counting it here counts those blocks twice.
308+
p.totalBlocksPruned += blocksPruned
303309
p.totalDocsSubmitted += totalSubmitted
304310
p.lastPruneTime = time.Now()
305311
p.mu.Unlock()

pkg/pruner/pruner_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package pruner
22

33
import (
44
"context"
5+
"errors"
56
"os"
67
"path/filepath"
78
"testing"
@@ -160,6 +161,45 @@ func TestPurgeStopsOnCancelledContext(t *testing.T) {
160161
require.Zero(t, submitted)
161162
}
162163

164+
// A block collection whose purge fails is re-queued, so the same blocks are drained and
165+
// counted again later. Counting them on the failed cycle too makes the total exceed the
166+
// blocks that were ever pruned.
167+
func TestBlockCounterIgnoresAFailedBlockPurge(t *testing.T) {
168+
cols := DefaultCollectionConfig()
169+
170+
q := NewEventQueue(cols)
171+
q.Push(cols.BlockCollection, testDocID(1))
172+
result := q.DrainDocs(1)
173+
require.NotNil(t, result)
174+
require.Equal(t, 1, result.BlockCount)
175+
176+
p := &Pruner{cfg: &Config{Enabled: true}, collections: cols, stopChan: make(chan struct{})}
177+
p.purgeDocs = func(context.Context, []client.DocID) error {
178+
return errors.New("purge failed")
179+
}
180+
181+
require.NoError(t, p.purgeFromDrainResult(context.Background(), q, result))
182+
183+
require.Zero(t, p.totalBlocksPruned, "blocks that were re-queued must not count as pruned")
184+
require.Equal(t, 1, q.BlockCount(), "guard: the blocks are back on the queue")
185+
}
186+
187+
// The counter still moves on the path that did purge.
188+
func TestBlockCounterCountsASuccessfulBlockPurge(t *testing.T) {
189+
cols := DefaultCollectionConfig()
190+
191+
q := NewEventQueue(cols)
192+
q.Push(cols.BlockCollection, testDocID(1))
193+
result := q.DrainDocs(1)
194+
require.NotNil(t, result)
195+
196+
p := &Pruner{cfg: &Config{Enabled: true}, collections: cols, stopChan: make(chan struct{})}
197+
p.purgeDocs = func(context.Context, []client.DocID) error { return nil }
198+
199+
require.NoError(t, p.purgeFromDrainResult(context.Background(), q, result))
200+
require.Equal(t, int64(1), p.totalBlocksPruned)
201+
}
202+
163203
// DrainDocs empties every collection up front, so a cycle that stops part-way has to re-queue the
164204
// collections it never reached as well as the one it stopped on. Nothing else re-adds a document
165205
// once it has replicated, so anything left behind is never pruned.

0 commit comments

Comments
 (0)