mirror of
https://github.com/hanzoai/tasks.git
synced 2026-10-04 02:04:03 +00:00
## 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`.
714 lines
25 KiB
Go
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))
|
|
}
|