Files
tasks/common/persistence/sql/sqlplugin/tests/queue_v2.go
T
Alex ShtinandGitHub 8e8f1b0f7c Remove license header from every file (#7689)
## What changed?
<!-- Describe what has changed in this PR -->
Remove license header from every file. Because it is really hard to
follow in this PR here is the summary:
1. License header is removed from all `.go` and `.proto` files
:fireworks::fireworks:🎆.
2. `LICENSE` file in the root directory has only Temporal and Uber
copyrights.
3. 5 other `LICENSE` files added to the packages which have copyrights
different from Temporal and Uber: Datadog, Xargin, "Mat Ryer, Tyler
Bunnell and contributors".
4. `license_file` flag is removed from all code generation tools.
5. `copyright_file` flag is removed from `go:generate mockgen`
directive.
6. All copyright related targets are removed from `Makefile`.
7. Updated Temporal copyright year to 2025 everywhere.

## Why?
<!-- Tell your future self why have you made these changes -->
I double checked with legal department that it is not needed to have
license header in every file. One file per repo is enough. I put all
copyrights to the root `LICENSE` file and removed header from all other
files. Also updated tools and `Makefile`.
2025-05-01 18:50:21 -07:00

714 lines
25 KiB
Go

package tests
import (
"context"
"database/sql"
"errors"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
enumspb "go.temporal.io/api/enums/v1"
"go.temporal.io/api/serviceerror"
persistencespb "go.temporal.io/server/api/persistence/v1"
"go.temporal.io/server/common/log"
"go.temporal.io/server/common/log/tag"
"go.temporal.io/server/common/persistence"
"go.temporal.io/server/common/persistence/persistencetest"
"go.temporal.io/server/common/persistence/serialization"
persistencesql "go.temporal.io/server/common/persistence/sql"
"go.temporal.io/server/common/persistence/sql/sqlplugin"
)
var (
ErrGetLastMessageIdFailed = errors.New("getLastMessageId error")
ErrTxBeginFailed = errors.New("txBegin error")
ErrInsertFailed = errors.New("insert error")
ErrTxRollbackFailed = errors.New("txRollBack err")
ErrTxCommitFailed = errors.New("txCommit err")
ErrRangeSelectFailed = errors.New("rangeSelect err")
ErrSelectMetadataFailed = errors.New("selectFromMetadata err")
ErrInsertMetadataFailed = errors.New("insertMetadataFailed")
ErrRangeDeleteFailed = errors.New("rangeDeleteFailed")
ErrUpdateMetadataFailed = errors.New("updateMetadataFailed")
ErrSelectQueueNames = errors.New("selectQueueNamesFailed")
)
type (
faultyDB struct {
sqlplugin.DB
getLastMessageIdErr error
txBeginErr error
txCommitErr error
insertErr error
txRollbackErr error
rangeSelectError error
selectMetadataError error
insertMetadataError error
rangeDeleteError error
updateMetadataError error
selectQueueNamesError error
commitCalls int
}
faultyTx struct {
db *faultyDB
sqlplugin.Tx
commitCalls *int
}
logRecorder struct {
log.Logger
errMsgs []string
}
)
func (db *faultyDB) BeginTx(ctx context.Context) (sqlplugin.Tx, error) {
if db.txBeginErr != nil {
return nil, db.txBeginErr
}
tx, err := db.DB.BeginTx(ctx)
if err != nil {
return nil, err
}
return &faultyTx{db: db, commitCalls: &db.commitCalls, Tx: tx}, nil
}
func (tx *faultyTx) InsertIntoQueueV2Messages(ctx context.Context, row []sqlplugin.QueueV2MessageRow) (sql.Result, error) {
if tx.db.insertErr != nil {
return nil, tx.db.insertErr
}
return tx.Tx.InsertIntoQueueV2Messages(ctx, row)
}
func (tx *faultyTx) GetLastEnqueuedMessageIDForUpdateV2(ctx context.Context, filter sqlplugin.QueueV2Filter) (int64, error) {
if tx.db.getLastMessageIdErr != nil {
return 0, tx.db.getLastMessageIdErr
}
return tx.Tx.GetLastEnqueuedMessageIDForUpdateV2(ctx, filter)
}
func (db *faultyDB) GetLastEnqueuedMessageIDForUpdateV2(ctx context.Context, filter sqlplugin.QueueV2Filter) (int64, error) {
if db.getLastMessageIdErr != nil {
return 0, db.getLastMessageIdErr
}
return db.DB.GetLastEnqueuedMessageIDForUpdateV2(ctx, filter)
}
func (db *faultyDB) RangeSelectFromQueueV2Messages(ctx context.Context, filter sqlplugin.QueueV2MessagesFilter) ([]sqlplugin.QueueV2MessageRow, error) {
return []sqlplugin.QueueV2MessageRow{}, db.rangeSelectError
}
func (db *faultyDB) SelectFromQueueV2Metadata(ctx context.Context, filter sqlplugin.QueueV2MetadataFilter) (*sqlplugin.QueueV2MetadataRow, error) {
if db.selectMetadataError != nil {
return &sqlplugin.QueueV2MetadataRow{}, db.selectMetadataError
}
return db.DB.SelectFromQueueV2Metadata(ctx, filter)
}
func (db *faultyDB) SelectNameFromQueueV2Metadata(ctx context.Context, filter sqlplugin.QueueV2MetadataTypeFilter) ([]sqlplugin.QueueV2MetadataRow, error) {
if db.selectQueueNamesError != nil {
return nil, db.selectQueueNamesError
}
return db.DB.SelectNameFromQueueV2Metadata(ctx, filter)
}
func (db *faultyDB) SelectFromQueueV2MetadataForUpdate(ctx context.Context, filter sqlplugin.QueueV2MetadataFilter) (*sqlplugin.QueueV2MetadataRow, error) {
if db.selectMetadataError != nil {
return &sqlplugin.QueueV2MetadataRow{}, db.selectMetadataError
}
return db.DB.SelectFromQueueV2MetadataForUpdate(ctx, filter)
}
func (tx *faultyTx) SelectFromQueueV2Metadata(ctx context.Context, filter sqlplugin.QueueV2MetadataFilter) (*sqlplugin.QueueV2MetadataRow, error) {
if tx.db.selectMetadataError != nil {
return &sqlplugin.QueueV2MetadataRow{}, tx.db.selectMetadataError
}
return tx.Tx.SelectFromQueueV2Metadata(ctx, filter)
}
func (tx *faultyTx) SelectFromQueueV2MetadataForUpdate(ctx context.Context, filter sqlplugin.QueueV2MetadataFilter) (*sqlplugin.QueueV2MetadataRow, error) {
if tx.db.selectMetadataError != nil {
return &sqlplugin.QueueV2MetadataRow{}, tx.db.selectMetadataError
}
return tx.Tx.SelectFromQueueV2MetadataForUpdate(ctx, filter)
}
func (db *faultyDB) InsertIntoQueueV2Metadata(ctx context.Context, row *sqlplugin.QueueV2MetadataRow) (sql.Result, error) {
if db.insertMetadataError != nil {
return nil, db.insertMetadataError
}
return db.DB.InsertIntoQueueV2Metadata(ctx, row)
}
func (tx *faultyTx) RangeDeleteFromQueueV2Messages(ctx context.Context, filter sqlplugin.QueueV2MessagesFilter) (sql.Result, error) {
if tx.db.rangeDeleteError != nil {
return nil, tx.db.rangeDeleteError
}
return tx.Tx.RangeDeleteFromQueueV2Messages(ctx, filter)
}
func (tx *faultyTx) UpdateQueueV2Metadata(ctx context.Context, row *sqlplugin.QueueV2MetadataRow) (sql.Result, error) {
if tx.db.updateMetadataError != nil {
return nil, tx.db.updateMetadataError
}
return tx.Tx.UpdateQueueV2Metadata(ctx, row)
}
func (tx *faultyTx) Rollback() error {
if err := tx.Tx.Rollback(); err != nil {
return err
}
return tx.db.txRollbackErr
}
func (tx *faultyTx) Commit() error {
*tx.commitCalls++
if tx.db.txCommitErr != nil {
err := tx.Rollback()
if err != nil {
return err
}
return tx.db.txCommitErr
}
return tx.Tx.Commit()
}
func (l *logRecorder) Error(msg string, _ ...tag.Tag) {
l.errMsgs = append(l.errMsgs, msg)
}
func RunSQLQueueV2TestSuite(t *testing.T, baseDB sqlplugin.DB) {
ctx := context.Background()
t.Run("TestListQueueFailsToGetLastMessageID", func(t *testing.T) {
t.Parallel()
testListQueueFailsToGetLastMessageID(ctx, t, baseDB)
})
t.Run("TestListQueueFailsToExtractQueueMetadata", func(t *testing.T) {
t.Parallel()
testListQueueFailsToExtractQueueMetadata(ctx, t, baseDB)
})
t.Run("GetPartitionFailsForListQueues", func(t *testing.T) {
t.Parallel()
testListQueuesGetPartitionFails(ctx, t, baseDB)
})
t.Run("QueueInsertFails", func(t *testing.T) {
t.Parallel()
testQueueInsertFails(ctx, t, baseDB)
})
t.Run("TxBeginFails", func(t *testing.T) {
t.Parallel()
testBeginTxFails(ctx, t, baseDB)
})
t.Run("TxCommitFails", func(t *testing.T) {
t.Parallel()
testCommitTxFails(ctx, t, baseDB)
})
t.Run("FailedToGetLastMessageIDFromDB", func(t *testing.T) {
t.Parallel()
testGetLastMessageIDFails(ctx, t, baseDB)
})
t.Run("FailedToGetLastMessageIDFromDB", func(t *testing.T) {
t.Parallel()
testRangeSelectFromQueueV2MessagesFails(ctx, t, baseDB)
})
t.Run("InsertIntoQueueV2MetadataFails", func(t *testing.T) {
t.Parallel()
testInsertIntoQueueV2MetadataFails(ctx, t, baseDB)
})
t.Run("GetPartitionFailsForRangeDelete", func(t *testing.T) {
t.Parallel()
testGetPartitionFailsForRangeDelete(ctx, t, baseDB)
})
t.Run("GetLastMessageIDForDeleteFails", func(t *testing.T) {
t.Parallel()
testGetLastMessageIDForDeleteFails(ctx, t, baseDB)
})
t.Run("RangeDeleteMessagesFails", func(t *testing.T) {
t.Parallel()
testRangeDeleteMessagesFails(ctx, t, baseDB)
})
t.Run("RangeDeleteActuallyDeletes", func(t *testing.T) {
t.Parallel()
testRangeDeleteActuallyDeletes(ctx, t, baseDB)
})
t.Run("UpdateMetadataFails", func(t *testing.T) {
t.Parallel()
testUpdateMetadataFails(ctx, t, baseDB)
})
t.Run("InvalidMetadataEncoding", func(t *testing.T) {
t.Parallel()
testInvalidMetadataEncoding(ctx, t, baseDB)
})
t.Run("InvalidMetadataPayload", func(t *testing.T) {
t.Parallel()
testInvalidMetadataPayload(ctx, t, baseDB)
})
t.Run("SelectMetadataFails", func(t *testing.T) {
t.Parallel()
testSelectMetadataFails(ctx, t, baseDB)
})
t.Run("SelectNameFromQueueV2MetadataFails", func(t *testing.T) {
t.Parallel()
testSelectNameFromQueueV2MetadataFails(ctx, t, baseDB)
})
t.Run("SelectNameFromQueueV2NegativeToken", func(t *testing.T) {
t.Parallel()
testSelectNameFromQueueV2NegativeToken(ctx, t, baseDB)
})
}
func testQueueInsertFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
insertErr: ErrInsertFailed,
txRollbackErr: ErrTxRollbackFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueName,
})
require.NoError(t, err)
_, err = persistencetest.EnqueueMessage(context.Background(), q, queueType, queueName)
require.Error(t, err)
assert.ErrorContains(t, err, "insert error")
require.Len(t, logger.errMsgs, 1)
assert.Contains(t, logger.errMsgs[0], "transaction rollback error")
assert.Equal(t, db.commitCalls, 0)
}
func testCommitTxFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
txCommitErr: ErrTxCommitFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueName,
})
require.NoError(t, err)
_, err = persistencetest.EnqueueMessage(context.Background(), q, queueType, queueName)
require.Error(t, err)
assert.ErrorContains(t, err, "EnqueueMessage failed")
assert.Equal(t, db.commitCalls, 1)
}
func testBeginTxFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
txBeginErr: ErrTxBeginFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueName,
})
require.NoError(t, err)
_, err = persistencetest.EnqueueMessage(context.Background(), q, queueType, queueName)
require.Error(t, err)
assert.ErrorContains(t, err, "txBegin error")
assert.Equal(t, db.commitCalls, 0)
}
func testGetLastMessageIDFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
getLastMessageIdErr: ErrGetLastMessageIdFailed,
txRollbackErr: ErrTxRollbackFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueName,
})
require.NoError(t, err)
_, err = persistencetest.EnqueueMessage(context.Background(), q, queueType, queueName)
require.Error(t, err)
assert.ErrorContains(t, err, "failed to get next messageId")
assert.Equal(t, db.commitCalls, 0)
}
func testRangeSelectFromQueueV2MessagesFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
rangeSelectError: ErrRangeSelectFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueName,
})
require.NoError(t, err)
_, err = q.ReadMessages(context.Background(), &persistence.InternalReadMessagesRequest{
QueueType: queueType,
QueueName: queueName,
PageSize: 1,
NextPageToken: nil,
})
require.Error(t, err)
assert.ErrorContains(t, err, "RangeSelectFromQueueV2Messages operation failed")
}
func testInsertIntoQueueV2MetadataFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
insertMetadataError: ErrInsertMetadataFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueName,
})
require.Error(t, err)
assert.ErrorContains(t, err, "InsertIntoQueueV2Metadata operation failed")
}
func testGetPartitionFailsForRangeDelete(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(baseDB, logger)
queuePB := persistencespb.Queue{
Partitions: map[int32]*persistencespb.QueuePartition{
0: {},
1: {},
},
}
bytes, _ := queuePB.Marshal()
row := sqlplugin.QueueV2MetadataRow{
QueueType: queueType,
QueueName: queueName,
MetadataPayload: bytes,
MetadataEncoding: enumspb.ENCODING_TYPE_PROTO3.String(),
}
_, err := baseDB.InsertIntoQueueV2Metadata(ctx, &row)
require.NoError(t, err)
_, err = q.RangeDeleteMessages(context.Background(), &persistence.InternalRangeDeleteMessagesRequest{
QueueType: persistence.QueueTypeHistoryNormal,
QueueName: "test-queue-" + t.Name(),
InclusiveMaxMessageMetadata: persistence.MessageMetadata{ID: 0},
})
assert.Error(t, err)
assert.ErrorContains(t, err, "partitions")
}
func testGetLastMessageIDForDeleteFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
getLastMessageIdErr: ErrGetLastMessageIdFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueName,
})
require.NoError(t, err)
_, err = q.RangeDeleteMessages(context.Background(), &persistence.InternalRangeDeleteMessagesRequest{
QueueType: persistence.QueueTypeHistoryNormal,
QueueName: "test-queue-" + t.Name(),
InclusiveMaxMessageMetadata: persistence.MessageMetadata{ID: 0},
})
assert.Error(t, err)
assert.ErrorContains(t, err, "getLastMessageId error")
}
func testRangeDeleteMessagesFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
rangeDeleteError: ErrRangeDeleteFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueName,
})
require.NoError(t, err)
persistencetest.EnqueueMessagesForDelete(t, q, queueName, queueType)
_, err = q.RangeDeleteMessages(context.Background(), &persistence.InternalRangeDeleteMessagesRequest{
QueueType: queueType,
QueueName: queueName,
InclusiveMaxMessageMetadata: persistence.MessageMetadata{ID: 0},
})
assert.Error(t, err)
assert.ErrorContains(t, err, "rangeDeleteFailed")
}
func testUpdateMetadataFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
updateMetadataError: ErrUpdateMetadataFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueName,
})
require.NoError(t, err)
persistencetest.EnqueueMessagesForDelete(t, q, queueName, queueType)
_, err = q.RangeDeleteMessages(context.Background(), &persistence.InternalRangeDeleteMessagesRequest{
QueueType: queueType,
QueueName: queueName,
InclusiveMaxMessageMetadata: persistence.MessageMetadata{ID: 0},
})
assert.Error(t, err)
assert.ErrorContains(t, err, "updateMetadataFailed")
}
func testSelectMetadataFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
selectMetadataError: ErrSelectMetadataFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.ReadMessages(ctx, &persistence.InternalReadMessagesRequest{
QueueType: queueType,
QueueName: queueName,
PageSize: 10,
})
assert.Error(t, err)
assert.ErrorContains(t, err, ErrSelectMetadataFailed.Error())
_, err = persistencetest.EnqueueMessage(context.Background(), q, queueType, queueName)
assert.Error(t, err)
assert.ErrorContains(t, err, ErrSelectMetadataFailed.Error())
_, err = q.RangeDeleteMessages(context.Background(), &persistence.InternalRangeDeleteMessagesRequest{
QueueType: queueType,
QueueName: queueName,
InclusiveMaxMessageMetadata: persistence.MessageMetadata{ID: 0},
})
assert.Error(t, err)
assert.ErrorAs(t, err, new(*serviceerror.Unavailable))
}
func testInvalidMetadataPayload(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(baseDB, logger)
row := sqlplugin.QueueV2MetadataRow{
QueueType: queueType,
QueueName: queueName,
MetadataPayload: []byte("invalid_payload"),
MetadataEncoding: enumspb.ENCODING_TYPE_PROTO3.String(),
}
_, err := baseDB.InsertIntoQueueV2Metadata(ctx, &row)
require.NoError(t, err)
_, err = q.ReadMessages(context.Background(), &persistence.InternalReadMessagesRequest{
QueueType: queueType,
QueueName: queueName,
PageSize: 10,
})
assert.Error(t, err)
assert.ErrorAs(t, err, new(*serialization.DeserializationError))
}
func testInvalidMetadataEncoding(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryNormal
queueName := "test-queue-" + t.Name()
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(baseDB, logger)
row := sqlplugin.QueueV2MetadataRow{
QueueType: queueType,
QueueName: queueName,
MetadataPayload: []byte("test"),
MetadataEncoding: "invalid_encoding",
}
_, err := baseDB.InsertIntoQueueV2Metadata(ctx, &row)
require.NoError(t, err)
_, err = q.ReadMessages(context.Background(), &persistence.InternalReadMessagesRequest{
QueueType: queueType,
QueueName: queueName,
PageSize: 10,
})
assert.Error(t, err)
assert.ErrorAs(t, err, new(*serialization.UnknownEncodingTypeError))
_, err = persistencetest.EnqueueMessage(context.Background(), q, queueType, queueName)
assert.Error(t, err)
assert.ErrorAs(t, err, new(*serialization.UnknownEncodingTypeError))
_, err = q.RangeDeleteMessages(context.Background(), &persistence.InternalRangeDeleteMessagesRequest{
QueueType: queueType,
QueueName: queueName,
InclusiveMaxMessageMetadata: persistence.MessageMetadata{ID: 0},
})
assert.Error(t, err)
assert.ErrorAs(t, err, new(*serviceerror.Unavailable))
}
func testRangeDeleteActuallyDeletes(ctx context.Context, t *testing.T, db sqlplugin.DB) {
queueKey := persistencetest.GetQueueKey(t)
queueType := persistence.QueueTypeHistoryNormal
q := persistencesql.NewQueueV2(db, log.NewTestLogger())
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueKey.GetQueueName(),
})
require.NoError(t, err)
for i := 0; i < 3; i++ {
_, err = persistencetest.EnqueueMessage(context.Background(), q, queueType, queueKey.GetQueueName())
require.NoError(t, err)
}
resp, err := q.RangeDeleteMessages(context.Background(), &persistence.InternalRangeDeleteMessagesRequest{
QueueType: queueType,
QueueName: queueKey.GetQueueName(),
InclusiveMaxMessageMetadata: persistence.MessageMetadata{ID: persistence.FirstQueueMessageID + 2},
})
require.NoError(t, err)
assert.Equal(t, int64(3), resp.MessagesDeleted)
result, err := q.ReadMessages(ctx, &persistence.InternalReadMessagesRequest{
QueueType: queueType,
QueueName: queueKey.GetQueueName(),
PageSize: 10,
})
require.NoError(t, err)
assert.Empty(t, result.Messages)
messages, err := db.RangeSelectFromQueueV2Messages(ctx, sqlplugin.QueueV2MessagesFilter{
QueueType: queueType,
QueueName: queueKey.GetQueueName(),
MinMessageID: 0,
MaxMessageID: 100,
PageSize: 10,
})
require.NoError(t, err)
if assert.Len(t, messages, 1) {
assert.Equal(t, int64(persistence.FirstQueueMessageID+2), messages[0].MessageID)
}
response, err := persistencetest.EnqueueMessage(context.Background(), q, queueType, queueKey.GetQueueName())
require.NoError(t, err)
assert.Equal(t, int64(persistence.FirstQueueMessageID+3), response.Metadata.ID)
}
func testSelectNameFromQueueV2MetadataFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryDLQ
db := &faultyDB{
DB: baseDB,
selectQueueNamesError: ErrSelectQueueNames,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.ListQueues(ctx, &persistence.InternalListQueuesRequest{
QueueType: queueType,
PageSize: 10,
NextPageToken: nil,
})
assert.Error(t, err)
assert.ErrorContains(t, err, "SelectNameFromQueueV2Metadata operation failed")
}
func testSelectNameFromQueueV2NegativeToken(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
queueType := persistence.QueueTypeHistoryDLQ
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(baseDB, logger)
_, err := q.ListQueues(ctx, &persistence.InternalListQueuesRequest{
QueueType: queueType,
PageSize: 1,
NextPageToken: persistence.GetNextPageTokenForListQueues(-1),
})
require.Error(t, err)
require.ErrorIs(t, err, persistence.ErrNegativeListQueuesOffset)
}
func testListQueuesGetPartitionFails(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
// Using a different QueueType to prevent this test from failing because of queues created in previous tests.
queueType := persistence.QueueV2Type(4)
queueName := "test-queue-" + t.Name()
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(baseDB, logger)
queuePB := persistencespb.Queue{
Partitions: map[int32]*persistencespb.QueuePartition{
0: {},
1: {},
},
}
bytes, _ := queuePB.Marshal()
row := sqlplugin.QueueV2MetadataRow{
QueueType: queueType,
QueueName: queueName,
MetadataPayload: bytes,
MetadataEncoding: enumspb.ENCODING_TYPE_PROTO3.String(),
}
_, err := baseDB.InsertIntoQueueV2Metadata(ctx, &row)
require.NoError(t, err)
_, err = q.ListQueues(context.Background(), &persistence.InternalListQueuesRequest{
QueueType: queueType,
PageSize: 100,
})
assert.Error(t, err)
assert.ErrorContains(t, err, "partitions")
}
func testListQueueFailsToGetLastMessageID(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
// Using a different QueueType to prevent this test from failing because of queues created in previous tests.
queueType := persistence.QueueV2Type(5)
queueName := "test-queue-" + t.Name()
db := &faultyDB{
DB: baseDB,
getLastMessageIdErr: ErrGetLastMessageIdFailed,
}
logger := &logRecorder{Logger: log.NewTestLogger()}
q := persistencesql.NewQueueV2(db, logger)
_, err := q.CreateQueue(ctx, &persistence.InternalCreateQueueRequest{
QueueType: queueType,
QueueName: queueName,
})
assert.NoError(t, err)
_, err = q.ListQueues(ctx, &persistence.InternalListQueuesRequest{
QueueType: queueType,
PageSize: 100,
})
assert.Error(t, err)
assert.ErrorContains(t, err, ErrGetLastMessageIdFailed.Error())
}
func testListQueueFailsToExtractQueueMetadata(ctx context.Context, t *testing.T, baseDB sqlplugin.DB) {
// Using a different QueueType to prevent this test from failing because of queues created in previous tests.
queueType := persistence.QueueV2Type(6)
queueName := "test-queue-" + t.Name()
q := persistencesql.NewQueueV2(baseDB, log.NewTestLogger())
row := sqlplugin.QueueV2MetadataRow{
QueueType: queueType,
QueueName: queueName,
MetadataPayload: []byte("test"),
MetadataEncoding: "invalid_encoding",
}
_, err := baseDB.InsertIntoQueueV2Metadata(ctx, &row)
assert.NoError(t, err)
_, err = q.ListQueues(ctx, &persistence.InternalListQueuesRequest{
QueueType: queueType,
PageSize: 100,
})
assert.Error(t, err)
assert.ErrorAs(t, err, new(*serialization.UnknownEncodingTypeError))
}