go.temporal.io/server@v1.23.0/common/persistence/tests/task_queue.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2020 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2020 Uber Technologies, Inc.
     6  //
     7  // Permission is hereby granted, free of charge, to any person obtaining a copy
     8  // of this software and associated documentation files (the "Software"), to deal
     9  // in the Software without restriction, including without limitation the rights
    10  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11  // copies of the Software, and to permit persons to whom the Software is
    12  // furnished to do so, subject to the following conditions:
    13  //
    14  // The above copyright notice and this permission notice shall be included in
    15  // all copies or substantial portions of the Software.
    16  //
    17  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23  // THE SOFTWARE.
    24  
    25  package tests
    26  
    27  import (
    28  	"context"
    29  	"math/rand"
    30  	"testing"
    31  	"time"
    32  
    33  	"github.com/google/uuid"
    34  	"github.com/stretchr/testify/require"
    35  	"github.com/stretchr/testify/suite"
    36  	enumspb "go.temporal.io/api/enums/v1"
    37  	"go.temporal.io/api/serviceerror"
    38  	"google.golang.org/protobuf/types/known/timestamppb"
    39  
    40  	persistencespb "go.temporal.io/server/api/persistence/v1"
    41  	"go.temporal.io/server/common/debug"
    42  	"go.temporal.io/server/common/log"
    43  	p "go.temporal.io/server/common/persistence"
    44  	"go.temporal.io/server/common/persistence/serialization"
    45  	"go.temporal.io/server/common/testing/protorequire"
    46  )
    47  
    48  type (
    49  	TaskQueueSuite struct {
    50  		suite.Suite
    51  		*require.Assertions
    52  		protorequire.ProtoAssertions
    53  
    54  		stickyTTL     time.Duration
    55  		namespaceID   string
    56  		taskQueueName string
    57  		taskQueueType enumspb.TaskQueueType
    58  
    59  		taskManager p.TaskManager
    60  		logger      log.Logger
    61  
    62  		ctx    context.Context
    63  		cancel context.CancelFunc
    64  	}
    65  )
    66  
    67  func NewTaskQueueSuite(
    68  	t *testing.T,
    69  	taskManager p.TaskStore,
    70  	logger log.Logger,
    71  ) *TaskQueueSuite {
    72  	return &TaskQueueSuite{
    73  		Assertions:      require.New(t),
    74  		ProtoAssertions: protorequire.New(t),
    75  		taskManager: p.NewTaskManager(
    76  			taskManager,
    77  			serialization.NewSerializer(),
    78  		),
    79  		logger: logger,
    80  	}
    81  }
    82  
    83  func (s *TaskQueueSuite) SetupSuite() {
    84  }
    85  
    86  func (s *TaskQueueSuite) TearDownSuite() {
    87  }
    88  
    89  func (s *TaskQueueSuite) SetupTest() {
    90  	s.Assertions = require.New(s.T())
    91  	s.ctx, s.cancel = context.WithTimeout(context.Background(), 30*time.Second*debug.TimeoutMultiplier)
    92  
    93  	s.stickyTTL = time.Second * 10
    94  	s.namespaceID = uuid.New().String()
    95  	s.taskQueueName = uuid.New().String()
    96  	s.taskQueueType = enumspb.TaskQueueType(rand.Int31n(
    97  		int32(len(enumspb.TaskQueueType_value)) + 1),
    98  	)
    99  }
   100  
   101  func (s *TaskQueueSuite) TearDownTest() {
   102  	s.cancel()
   103  }
   104  
   105  func (s *TaskQueueSuite) TestCreate_Normal() {
   106  	rangID := rand.Int63()
   107  	taskQueue := s.createTaskQueue(rangID, enumspb.TASK_QUEUE_KIND_NORMAL)
   108  
   109  	s.assertEqualWithDB(rangID, taskQueue)
   110  }
   111  
   112  func (s *TaskQueueSuite) TestCreate_Sticky() {
   113  	rangID := rand.Int63()
   114  	taskQueue := s.createTaskQueue(rangID, enumspb.TASK_QUEUE_KIND_STICKY)
   115  
   116  	s.assertEqualWithDB(rangID, taskQueue)
   117  }
   118  
   119  func (s *TaskQueueSuite) TestCreate_Normal_Dup() {
   120  	rangID := rand.Int63()
   121  	taskQueue := s.createTaskQueue(rangID, enumspb.TASK_QUEUE_KIND_NORMAL)
   122  
   123  	_, err := s.taskManager.CreateTaskQueue(s.ctx, &p.CreateTaskQueueRequest{
   124  		RangeID:       rangID,
   125  		TaskQueueInfo: s.randomTaskQueueInfo(enumspb.TASK_QUEUE_KIND_NORMAL),
   126  	})
   127  	s.IsType(&p.ConditionFailedError{}, err)
   128  
   129  	s.assertEqualWithDB(rangID, taskQueue)
   130  }
   131  
   132  func (s *TaskQueueSuite) TestCreate_Sticky_Dup() {
   133  	rangID := rand.Int63()
   134  	taskQueue := s.createTaskQueue(rangID, enumspb.TASK_QUEUE_KIND_STICKY)
   135  
   136  	_, err := s.taskManager.CreateTaskQueue(s.ctx, &p.CreateTaskQueueRequest{
   137  		RangeID:       rangID,
   138  		TaskQueueInfo: s.randomTaskQueueInfo(enumspb.TASK_QUEUE_KIND_STICKY),
   139  	})
   140  	s.IsType(&p.ConditionFailedError{}, err)
   141  
   142  	s.assertEqualWithDB(rangID, taskQueue)
   143  }
   144  
   145  func (s *TaskQueueSuite) TestUpdate_Normal() {
   146  	prevRangeID := rand.Int63()
   147  	_ = s.createTaskQueue(prevRangeID, enumspb.TASK_QUEUE_KIND_NORMAL)
   148  
   149  	rangID := rand.Int63()
   150  	taskQueue := s.randomTaskQueueInfo(enumspb.TASK_QUEUE_KIND_NORMAL)
   151  	_, err := s.taskManager.UpdateTaskQueue(s.ctx, &p.UpdateTaskQueueRequest{
   152  		RangeID:       rangID,
   153  		TaskQueueInfo: taskQueue,
   154  
   155  		PrevRangeID: prevRangeID,
   156  	})
   157  	s.NoError(err)
   158  
   159  	s.assertEqualWithDB(rangID, taskQueue)
   160  }
   161  
   162  func (s *TaskQueueSuite) TestUpdate_Normal_Conflict() {
   163  	prevRangeID := rand.Int63()
   164  	taskQueue := s.createTaskQueue(prevRangeID, enumspb.TASK_QUEUE_KIND_NORMAL)
   165  
   166  	rangID := rand.Int63()
   167  	_, err := s.taskManager.UpdateTaskQueue(s.ctx, &p.UpdateTaskQueueRequest{
   168  		RangeID:       rangID,
   169  		TaskQueueInfo: s.randomTaskQueueInfo(enumspb.TASK_QUEUE_KIND_NORMAL),
   170  
   171  		PrevRangeID: rand.Int63(),
   172  	})
   173  	s.IsType(&p.ConditionFailedError{}, err)
   174  
   175  	s.assertEqualWithDB(prevRangeID, taskQueue)
   176  }
   177  
   178  func (s *TaskQueueSuite) TestUpdate_Sticky() {
   179  	prevRangeID := rand.Int63()
   180  	_ = s.createTaskQueue(prevRangeID, enumspb.TASK_QUEUE_KIND_STICKY)
   181  
   182  	rangID := rand.Int63()
   183  	taskQueue := s.randomTaskQueueInfo(enumspb.TASK_QUEUE_KIND_STICKY)
   184  	_, err := s.taskManager.UpdateTaskQueue(s.ctx, &p.UpdateTaskQueueRequest{
   185  		RangeID:       rangID,
   186  		TaskQueueInfo: taskQueue,
   187  
   188  		PrevRangeID: prevRangeID,
   189  	})
   190  	s.NoError(err)
   191  
   192  	s.assertEqualWithDB(rangID, taskQueue)
   193  }
   194  
   195  func (s *TaskQueueSuite) TestUpdate_Sticky_Conflict() {
   196  	prevRangeID := rand.Int63()
   197  	taskQueue := s.createTaskQueue(prevRangeID, enumspb.TASK_QUEUE_KIND_STICKY)
   198  
   199  	rangID := rand.Int63()
   200  	_, err := s.taskManager.UpdateTaskQueue(s.ctx, &p.UpdateTaskQueueRequest{
   201  		RangeID:       rangID,
   202  		TaskQueueInfo: s.randomTaskQueueInfo(enumspb.TASK_QUEUE_KIND_STICKY),
   203  
   204  		PrevRangeID: rand.Int63(),
   205  	})
   206  	s.IsType(&p.ConditionFailedError{}, err)
   207  
   208  	s.assertEqualWithDB(prevRangeID, taskQueue)
   209  }
   210  
   211  func (s *TaskQueueSuite) TestDelete() {
   212  	rangeID := rand.Int63()
   213  	taskQueue := s.createTaskQueue(
   214  		rangeID,
   215  		enumspb.TaskQueueKind(rand.Int31n(
   216  			int32(len(enumspb.TaskQueueKind_value))+1),
   217  		),
   218  	)
   219  
   220  	err := s.taskManager.DeleteTaskQueue(s.ctx, &p.DeleteTaskQueueRequest{
   221  		TaskQueue: &p.TaskQueueKey{
   222  			NamespaceID:   taskQueue.NamespaceId,
   223  			TaskQueueName: taskQueue.Name,
   224  			TaskQueueType: taskQueue.TaskType,
   225  		},
   226  		RangeID: rangeID,
   227  	})
   228  	s.NoError(err)
   229  
   230  	s.assertMissingFromDB(taskQueue.NamespaceId, taskQueue.Name, taskQueue.TaskType)
   231  }
   232  
   233  func (s *TaskQueueSuite) TestDelete_Conflict() {
   234  	rangeID := rand.Int63()
   235  	taskQueue := s.createTaskQueue(
   236  		rangeID,
   237  		enumspb.TaskQueueKind(rand.Int31n(
   238  			int32(len(enumspb.TaskQueueKind_value))+1),
   239  		),
   240  	)
   241  
   242  	err := s.taskManager.DeleteTaskQueue(s.ctx, &p.DeleteTaskQueueRequest{
   243  		TaskQueue: &p.TaskQueueKey{
   244  			NamespaceID:   taskQueue.NamespaceId,
   245  			TaskQueueName: taskQueue.Name,
   246  			TaskQueueType: taskQueue.TaskType,
   247  		},
   248  		RangeID: rand.Int63(),
   249  	})
   250  	s.IsType(&p.ConditionFailedError{}, err)
   251  
   252  	s.assertEqualWithDB(rangeID, taskQueue)
   253  }
   254  
   255  func (s *TaskQueueSuite) TesList() {
   256  	// TODO there exists a SQL impl, but no cassandra impl ...
   257  }
   258  
   259  func (s *TaskQueueSuite) createTaskQueue(
   260  	rangeID int64,
   261  	taskQueueKind enumspb.TaskQueueKind,
   262  ) *persistencespb.TaskQueueInfo {
   263  	taskQueue := s.randomTaskQueueInfo(taskQueueKind)
   264  	_, err := s.taskManager.CreateTaskQueue(s.ctx, &p.CreateTaskQueueRequest{
   265  		RangeID:       rangeID,
   266  		TaskQueueInfo: taskQueue,
   267  	})
   268  	s.NoError(err)
   269  	return taskQueue
   270  }
   271  
   272  func (s *TaskQueueSuite) randomTaskQueueInfo(
   273  	taskQueueKind enumspb.TaskQueueKind,
   274  ) *persistencespb.TaskQueueInfo {
   275  	now := time.Now().UTC()
   276  	var expiryTime *timestamppb.Timestamp
   277  	if taskQueueKind == enumspb.TASK_QUEUE_KIND_STICKY {
   278  		expiryTime = timestamppb.New(now.Add(s.stickyTTL))
   279  	}
   280  
   281  	return &persistencespb.TaskQueueInfo{
   282  		NamespaceId:    s.namespaceID,
   283  		Name:           s.taskQueueName,
   284  		TaskType:       s.taskQueueType,
   285  		Kind:           taskQueueKind,
   286  		AckLevel:       rand.Int63(),
   287  		ExpiryTime:     expiryTime,
   288  		LastUpdateTime: timestamppb.New(now),
   289  	}
   290  }
   291  
   292  func (s *TaskQueueSuite) assertMissingFromDB(
   293  	namespaceID string,
   294  	taskQueue string,
   295  	taskType enumspb.TaskQueueType,
   296  ) {
   297  	_, err := s.taskManager.GetTaskQueue(s.ctx, &p.GetTaskQueueRequest{
   298  		NamespaceID: namespaceID,
   299  		TaskQueue:   taskQueue,
   300  		TaskType:    taskType,
   301  	})
   302  	s.IsType(&serviceerror.NotFound{}, err)
   303  }
   304  
   305  func (s *TaskQueueSuite) assertEqualWithDB(
   306  	rangeID int64,
   307  	taskQueueInfo *persistencespb.TaskQueueInfo,
   308  ) {
   309  	resp, err := s.taskManager.GetTaskQueue(s.ctx, &p.GetTaskQueueRequest{
   310  		NamespaceID: taskQueueInfo.NamespaceId,
   311  		TaskQueue:   taskQueueInfo.Name,
   312  		TaskType:    taskQueueInfo.TaskType,
   313  	})
   314  	s.NoError(err)
   315  
   316  	s.Equal(rangeID, resp.RangeID)
   317  	s.ProtoEqual(taskQueueInfo, resp.TaskQueueInfo)
   318  }