storj/satellite/satellitedb/reverifyqueue_test.go
paul cannon 2617925f8d satellite/audit: Split Reverifier from Verifier
Adding a new worker comparable to Verifier, called Reverifier; as the
name suggests, it will be used for reverifications, whereas Verifier
will be used for verifications.

This allows distinct logging from the two classes, plus we can add some
configuration that is specific to the Reverifier.

There is a slight modification to GetNextJob that goes along with this.

This should have no impact on operational concerns.

Refs: https://github.com/storj/storj/issues/5251
Change-Id: Ie60d2d833bc5db8660bb463dd93c764bb40fc49c
2022-12-05 09:55:49 -06:00

153 lines
5.0 KiB
Go

// Copyright (C) 2022 Storj Labs, Inc.
// See LICENSE for copying information.
package satellitedb_test
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/require"
"storj.io/common/sync2"
"storj.io/common/testcontext"
"storj.io/common/testrand"
"storj.io/storj/satellite"
"storj.io/storj/satellite/audit"
"storj.io/storj/satellite/metabase"
"storj.io/storj/satellite/satellitedb/satellitedbtest"
)
func randomLocator() *audit.PieceLocator {
return &audit.PieceLocator{
StreamID: testrand.UUID(),
Position: metabase.SegmentPosition{
Part: uint32(testrand.Intn(1 << 10)),
Index: uint32(testrand.Intn(1 << 20)),
},
NodeID: testrand.NodeID(),
PieceNum: testrand.Intn(1 << 10),
}
}
const (
retryInterval = 30 * time.Minute
)
func TestReverifyQueue(t *testing.T) {
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
reverifyQueue := db.ReverifyQueue()
locator1 := randomLocator()
locator2 := randomLocator()
err := reverifyQueue.Insert(ctx, locator1)
require.NoError(t, err)
// Postgres/Cockroach have only microsecond time resolution, so make
// sure at least 1us has elapsed before inserting the second.
sync2.Sleep(ctx, time.Microsecond)
err = reverifyQueue.Insert(ctx, locator2)
require.NoError(t, err)
job1, err := reverifyQueue.GetNextJob(ctx, retryInterval)
require.NoError(t, err)
require.Equal(t, *locator1, job1.Locator)
require.EqualValues(t, 1, job1.ReverifyCount)
job2, err := reverifyQueue.GetNextJob(ctx, retryInterval)
require.NoError(t, err)
require.Equal(t, *locator2, job2.Locator)
require.EqualValues(t, 1, job2.ReverifyCount)
require.Truef(t, job1.InsertedAt.Before(job2.InsertedAt), "job1 [%s] should have an earlier insertion time than job2 [%s]", job1.InsertedAt, job2.InsertedAt)
_, err = reverifyQueue.GetNextJob(ctx, retryInterval)
require.Truef(t, audit.ErrEmptyQueue.Has(err), "expected empty queue error, but got error %+v", err)
// pretend that ReverifyRetryInterval has elapsed
reverifyQueueTest := reverifyQueue.(interface {
TestingFudgeUpdateTime(ctx context.Context, piece *audit.PieceLocator, updateTime time.Time) error
})
err = reverifyQueueTest.TestingFudgeUpdateTime(ctx, locator1, time.Now().Add(-retryInterval))
require.NoError(t, err)
// job 1 should be eligible for a new worker to take over now (whatever
// worker acquired job 1 before is presumed to have died or timed out).
job3, err := reverifyQueue.GetNextJob(ctx, retryInterval)
require.NoError(t, err)
require.Equal(t, *locator1, job3.Locator)
require.EqualValues(t, 2, job3.ReverifyCount)
wasDeleted, err := reverifyQueue.Remove(ctx, locator1)
require.NoError(t, err)
require.True(t, wasDeleted)
wasDeleted, err = reverifyQueue.Remove(ctx, locator2)
require.NoError(t, err)
require.True(t, wasDeleted)
wasDeleted, err = reverifyQueue.Remove(ctx, locator1)
require.NoError(t, err)
require.False(t, wasDeleted)
_, err = reverifyQueue.GetNextJob(ctx, retryInterval)
require.Truef(t, audit.ErrEmptyQueue.Has(err), "expected empty queue error, but got error %+v", err)
})
}
func TestReverifyQueueGetByNodeID(t *testing.T) {
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
reverifyQueue := db.ReverifyQueue()
locator1 := randomLocator()
locator2 := randomLocator()
locator3 := randomLocator()
// two jobs on the same node
locator3.NodeID = locator1.NodeID
err := reverifyQueue.Insert(ctx, locator1)
require.NoError(t, err)
// Postgres/Cockroach have only microsecond time resolution, so make
// sure at least 1us has elapsed between inserts.
sync2.Sleep(ctx, time.Microsecond)
err = reverifyQueue.Insert(ctx, locator2)
require.NoError(t, err)
sync2.Sleep(ctx, time.Microsecond)
err = reverifyQueue.Insert(ctx, locator3)
require.NoError(t, err)
job1, err := reverifyQueue.GetByNodeID(ctx, locator1.NodeID)
require.NoError(t, err)
// we got either locator1 or locator3
if job1.Locator.StreamID == locator1.StreamID {
require.Equal(t, locator1.NodeID, job1.Locator.NodeID)
require.Equal(t, locator1.PieceNum, job1.Locator.PieceNum)
require.Equal(t, locator1.Position, job1.Locator.Position)
} else {
require.Equal(t, locator3.StreamID, job1.Locator.StreamID)
require.Equal(t, locator3.NodeID, job1.Locator.NodeID)
require.Equal(t, locator3.PieceNum, job1.Locator.PieceNum)
require.Equal(t, locator3.Position, job1.Locator.Position)
}
job2, err := reverifyQueue.GetByNodeID(ctx, locator2.NodeID)
require.NoError(t, err)
require.Equal(t, locator2.StreamID, job2.Locator.StreamID)
require.Equal(t, locator2.NodeID, job2.Locator.NodeID)
require.Equal(t, locator2.PieceNum, job2.Locator.PieceNum)
require.Equal(t, locator2.Position, job2.Locator.Position)
// ask for a nonexistent node ID
job3, err := reverifyQueue.GetByNodeID(ctx, testrand.NodeID())
require.Error(t, err)
require.Truef(t, audit.ErrContainedNotFound.Has(err), "expected ErrContainedNotFound error but got %+v", err)
require.Nil(t, job3)
})
}