go.temporal.io/server@v1.23.0/common/persistence/tests/task_queue_task.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 "google.golang.org/protobuf/types/known/timestamppb" 38 39 clockspb "go.temporal.io/server/api/clock/v1" 40 persistencespb "go.temporal.io/server/api/persistence/v1" 41 "go.temporal.io/server/common/debug" 42 43 "go.temporal.io/server/common/log" 44 p "go.temporal.io/server/common/persistence" 45 "go.temporal.io/server/common/persistence/serialization" 46 "go.temporal.io/server/common/testing/protorequire" 47 ) 48 49 type ( 50 TaskQueueTaskSuite struct { 51 suite.Suite 52 *require.Assertions 53 54 stickyTTL time.Duration 55 taskTTL time.Duration 56 namespaceID string 57 taskQueueName string 58 taskQueueType enumspb.TaskQueueType 59 60 taskManager p.TaskManager 61 logger log.Logger 62 63 ctx context.Context 64 cancel context.CancelFunc 65 } 66 ) 67 68 func NewTaskQueueTaskSuite( 69 t *testing.T, 70 taskManager p.TaskStore, 71 logger log.Logger, 72 ) *TaskQueueTaskSuite { 73 return &TaskQueueTaskSuite{ 74 Assertions: require.New(t), 75 taskManager: p.NewTaskManager( 76 taskManager, 77 serialization.NewSerializer(), 78 ), 79 logger: logger, 80 } 81 } 82 83 func (s *TaskQueueTaskSuite) SetupSuite() { 84 } 85 86 func (s *TaskQueueTaskSuite) TearDownSuite() { 87 } 88 89 func (s *TaskQueueTaskSuite) 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.taskTTL = time.Second * 16 95 s.namespaceID = uuid.New().String() 96 s.taskQueueName = uuid.New().String() 97 s.taskQueueType = enumspb.TaskQueueType(rand.Int31n( 98 int32(len(enumspb.TaskQueueType_name)) + 1), 99 ) 100 } 101 102 func (s *TaskQueueTaskSuite) TearDownTest() { 103 s.cancel() 104 } 105 106 func (s *TaskQueueTaskSuite) TestCreateGet_Conflict() { 107 rangeID := rand.Int63() 108 taskQueue := s.createTaskQueue(rangeID) 109 110 taskID := rand.Int63() 111 task := s.randomTask(taskID) 112 _, err := s.taskManager.CreateTasks(s.ctx, &p.CreateTasksRequest{ 113 TaskQueueInfo: &p.PersistedTaskQueueInfo{ 114 RangeID: rand.Int63(), 115 Data: taskQueue, 116 }, 117 Tasks: []*persistencespb.AllocatedTaskInfo{task}, 118 }) 119 s.IsType(&p.ConditionFailedError{}, err) 120 121 resp, err := s.taskManager.GetTasks(s.ctx, &p.GetTasksRequest{ 122 NamespaceID: s.namespaceID, 123 TaskQueue: s.taskQueueName, 124 TaskType: s.taskQueueType, 125 InclusiveMinTaskID: taskID, 126 ExclusiveMaxTaskID: taskID + 1, 127 PageSize: 100, 128 NextPageToken: nil, 129 }) 130 s.NoError(err) 131 protorequire.ProtoSliceEqual(s.T(), []*persistencespb.AllocatedTaskInfo{}, resp.Tasks) 132 s.Nil(resp.NextPageToken) 133 } 134 135 func (s *TaskQueueTaskSuite) TestCreateGet_One() { 136 rangeID := rand.Int63() 137 taskQueue := s.createTaskQueue(rangeID) 138 139 taskID := rand.Int63() 140 task := s.randomTask(taskID) 141 _, err := s.taskManager.CreateTasks(s.ctx, &p.CreateTasksRequest{ 142 TaskQueueInfo: &p.PersistedTaskQueueInfo{ 143 RangeID: rangeID, 144 Data: taskQueue, 145 }, 146 Tasks: []*persistencespb.AllocatedTaskInfo{task}, 147 }) 148 s.NoError(err) 149 150 resp, err := s.taskManager.GetTasks(s.ctx, &p.GetTasksRequest{ 151 NamespaceID: s.namespaceID, 152 TaskQueue: s.taskQueueName, 153 TaskType: s.taskQueueType, 154 InclusiveMinTaskID: taskID, 155 ExclusiveMaxTaskID: taskID + 1, 156 PageSize: 100, 157 NextPageToken: nil, 158 }) 159 s.NoError(err) 160 protorequire.ProtoSliceEqual(s.T(), []*persistencespb.AllocatedTaskInfo{task}, resp.Tasks) 161 s.Nil(resp.NextPageToken) 162 } 163 164 func (s *TaskQueueTaskSuite) TestCreateGet_Multiple() { 165 numCreateBatch := 32 166 createBatchSize := 32 167 numTasks := int64(createBatchSize * numCreateBatch) 168 minTaskID := rand.Int63() 169 maxTaskID := minTaskID + numTasks 170 171 rangeID := rand.Int63() 172 taskQueue := s.createTaskQueue(rangeID) 173 174 var expectedTasks []*persistencespb.AllocatedTaskInfo 175 for i := 0; i < numCreateBatch; i++ { 176 var tasks []*persistencespb.AllocatedTaskInfo 177 for j := 0; j < createBatchSize; j++ { 178 taskID := minTaskID + int64(i*numCreateBatch+j) 179 task := s.randomTask(taskID) 180 tasks = append(tasks, task) 181 expectedTasks = append(expectedTasks, task) 182 } 183 _, err := s.taskManager.CreateTasks(s.ctx, &p.CreateTasksRequest{ 184 TaskQueueInfo: &p.PersistedTaskQueueInfo{ 185 RangeID: rangeID, 186 Data: taskQueue, 187 }, 188 Tasks: tasks, 189 }) 190 s.NoError(err) 191 } 192 193 var token []byte 194 var actualTasks []*persistencespb.AllocatedTaskInfo 195 for doContinue := true; doContinue; doContinue = len(token) > 0 { 196 resp, err := s.taskManager.GetTasks(s.ctx, &p.GetTasksRequest{ 197 NamespaceID: s.namespaceID, 198 TaskQueue: s.taskQueueName, 199 TaskType: s.taskQueueType, 200 InclusiveMinTaskID: minTaskID, 201 ExclusiveMaxTaskID: maxTaskID + 1, 202 PageSize: 1, 203 NextPageToken: token, 204 }) 205 s.NoError(err) 206 token = resp.NextPageToken 207 actualTasks = append(actualTasks, resp.Tasks...) 208 } 209 protorequire.ProtoSliceEqual(s.T(), expectedTasks, actualTasks) 210 } 211 212 func (s *TaskQueueTaskSuite) TestCreateDelete_One() { 213 rangeID := rand.Int63() 214 taskQueue := s.createTaskQueue(rangeID) 215 216 taskID := rand.Int63() 217 task := s.randomTask(taskID) 218 _, err := s.taskManager.CreateTasks(s.ctx, &p.CreateTasksRequest{ 219 TaskQueueInfo: &p.PersistedTaskQueueInfo{ 220 RangeID: rangeID, 221 Data: taskQueue, 222 }, 223 Tasks: []*persistencespb.AllocatedTaskInfo{task}, 224 }) 225 s.NoError(err) 226 227 err = s.taskManager.CompleteTask(s.ctx, &p.CompleteTaskRequest{ 228 TaskQueue: &p.TaskQueueKey{ 229 NamespaceID: s.namespaceID, 230 TaskQueueName: s.taskQueueName, 231 TaskQueueType: s.taskQueueType, 232 }, 233 TaskID: taskID, 234 }) 235 s.NoError(err) 236 237 resp, err := s.taskManager.GetTasks(s.ctx, &p.GetTasksRequest{ 238 NamespaceID: s.namespaceID, 239 TaskQueue: s.taskQueueName, 240 TaskType: s.taskQueueType, 241 InclusiveMinTaskID: taskID, 242 ExclusiveMaxTaskID: taskID + 1, 243 PageSize: 100, 244 NextPageToken: nil, 245 }) 246 s.NoError(err) 247 protorequire.ProtoSliceEqual(s.T(), []*persistencespb.AllocatedTaskInfo{}, resp.Tasks) 248 s.Nil(resp.NextPageToken) 249 } 250 251 func (s *TaskQueueTaskSuite) TestCreateDelete_Multiple() { 252 numCreateBatch := 32 253 createBatchSize := 32 254 numTasks := int64(createBatchSize * numCreateBatch) 255 minTaskID := rand.Int63() 256 maxTaskID := minTaskID + numTasks 257 258 rangeID := rand.Int63() 259 taskQueue := s.createTaskQueue(rangeID) 260 261 for i := 0; i < numCreateBatch; i++ { 262 var tasks []*persistencespb.AllocatedTaskInfo 263 for j := 0; j < createBatchSize; j++ { 264 taskID := minTaskID + int64(i*numCreateBatch+j) 265 task := s.randomTask(taskID) 266 tasks = append(tasks, task) 267 } 268 _, err := s.taskManager.CreateTasks(s.ctx, &p.CreateTasksRequest{ 269 TaskQueueInfo: &p.PersistedTaskQueueInfo{ 270 RangeID: rangeID, 271 Data: taskQueue, 272 }, 273 Tasks: tasks, 274 }) 275 s.NoError(err) 276 } 277 278 _, err := s.taskManager.CompleteTasksLessThan(s.ctx, &p.CompleteTasksLessThanRequest{ 279 NamespaceID: s.namespaceID, 280 TaskQueueName: s.taskQueueName, 281 TaskType: s.taskQueueType, 282 ExclusiveMaxTaskID: maxTaskID + 1, 283 Limit: int(numTasks), 284 }) 285 s.NoError(err) 286 287 resp, err := s.taskManager.GetTasks(s.ctx, &p.GetTasksRequest{ 288 NamespaceID: s.namespaceID, 289 TaskQueue: s.taskQueueName, 290 TaskType: s.taskQueueType, 291 InclusiveMinTaskID: minTaskID, 292 ExclusiveMaxTaskID: maxTaskID + 1, 293 PageSize: 100, 294 NextPageToken: nil, 295 }) 296 s.NoError(err) 297 protorequire.ProtoSliceEqual(s.T(), []*persistencespb.AllocatedTaskInfo{}, resp.Tasks) 298 s.Nil(resp.NextPageToken) 299 } 300 301 func (s *TaskQueueTaskSuite) createTaskQueue( 302 rangeID int64, 303 ) *persistencespb.TaskQueueInfo { 304 taskQueueKind := enumspb.TaskQueueKind(rand.Int31n( 305 int32(len(enumspb.TaskQueueKind_name)) + 1), 306 ) 307 taskQueue := s.randomTaskQueueInfo(taskQueueKind) 308 _, err := s.taskManager.CreateTaskQueue(s.ctx, &p.CreateTaskQueueRequest{ 309 RangeID: rangeID, 310 TaskQueueInfo: taskQueue, 311 }) 312 s.NoError(err) 313 return taskQueue 314 } 315 316 func (s *TaskQueueTaskSuite) randomTaskQueueInfo( 317 taskQueueKind enumspb.TaskQueueKind, 318 ) *persistencespb.TaskQueueInfo { 319 now := time.Now().UTC() 320 var expiryTime *timestamppb.Timestamp 321 if taskQueueKind == enumspb.TASK_QUEUE_KIND_STICKY { 322 expiryTime = timestamppb.New(now.Add(s.stickyTTL)) 323 } 324 325 return &persistencespb.TaskQueueInfo{ 326 NamespaceId: s.namespaceID, 327 Name: s.taskQueueName, 328 TaskType: s.taskQueueType, 329 Kind: taskQueueKind, 330 AckLevel: rand.Int63(), 331 ExpiryTime: expiryTime, 332 LastUpdateTime: timestamppb.New(now), 333 } 334 } 335 336 func (s *TaskQueueTaskSuite) randomTask( 337 taskID int64, 338 ) *persistencespb.AllocatedTaskInfo { 339 now := time.Now().UTC() 340 return &persistencespb.AllocatedTaskInfo{ 341 TaskId: taskID, 342 Data: &persistencespb.TaskInfo{ 343 NamespaceId: s.namespaceID, 344 WorkflowId: uuid.New().String(), 345 RunId: uuid.New().String(), 346 ScheduledEventId: rand.Int63(), 347 CreateTime: timestamppb.New(now), 348 ExpiryTime: timestamppb.New(now.Add(s.taskTTL)), 349 Clock: &clockspb.VectorClock{ 350 ClusterId: rand.Int63(), 351 ShardId: rand.Int31(), 352 Clock: rand.Int63(), 353 }, 354 }, 355 } 356 }