github.com/matrixorigin/matrixone@v1.2.0/pkg/taskservice/task_service_test.go (about) 1 // Copyright 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package taskservice 16 17 import ( 18 "context" 19 "fmt" 20 "os" 21 "os/exec" 22 "testing" 23 "time" 24 25 "github.com/matrixorigin/matrixone/pkg/common/moerr" 26 "github.com/matrixorigin/matrixone/pkg/common/runtime" 27 "github.com/matrixorigin/matrixone/pkg/pb/task" 28 "github.com/stretchr/testify/assert" 29 ) 30 31 func TestCreateAsyncTask(t *testing.T) { 32 store := NewMemTaskStorage() 33 s := NewTaskService(runtime.DefaultRuntime(), store) 34 defer func() { 35 assert.NoError(t, s.Close()) 36 }() 37 38 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 39 defer cancel() 40 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 41 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 42 43 v := mustGetTestAsyncTask(t, store, 1)[0] 44 assert.True(t, v.ID > 0) 45 assert.True(t, v.CreateAt > 0) 46 assert.Equal(t, int64(0), v.CompletedAt) 47 assert.Equal(t, task.TaskStatus_Created, v.Status) 48 assert.Equal(t, "", v.ParentTaskID) 49 assert.Equal(t, "", v.TaskRunner) 50 assert.Equal(t, uint32(0), v.Epoch) 51 assert.Equal(t, int64(0), v.LastHeartbeat) 52 assert.Nil(t, v.ExecuteResult) 53 assert.Equal(t, newTestTaskMetadata("t1"), v.Metadata) 54 } 55 56 func TestCreateBatch(t *testing.T) { 57 store := NewMemTaskStorage() 58 s := NewTaskService(runtime.DefaultRuntime(), store) 59 defer func() { 60 assert.NoError(t, s.Close()) 61 }() 62 63 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 64 defer cancel() 65 66 n := 10 67 var tasks []task.TaskMetadata 68 for i := 0; i < n; i++ { 69 tasks = append(tasks, newTestTaskMetadata(fmt.Sprintf("task-%d", i))) 70 } 71 72 assert.NoError(t, s.CreateBatch(ctx, tasks)) 73 74 values := mustGetTestAsyncTask(t, store, n) 75 for i := 0; i < n; i++ { 76 v := values[i] 77 assert.True(t, v.ID > 0) 78 assert.True(t, v.CreateAt > 0) 79 assert.Equal(t, int64(0), v.CompletedAt) 80 assert.Equal(t, task.TaskStatus_Created, v.Status) 81 assert.Equal(t, "", v.ParentTaskID) 82 assert.Equal(t, "", v.TaskRunner) 83 assert.Equal(t, uint32(0), v.Epoch) 84 assert.Equal(t, int64(0), v.LastHeartbeat) 85 assert.Nil(t, v.ExecuteResult) 86 assert.Equal(t, newTestTaskMetadata(fmt.Sprintf("task-%d", i)), v.Metadata) 87 } 88 } 89 90 func TestAllocate(t *testing.T) { 91 store := NewMemTaskStorage() 92 s := NewTaskService(runtime.DefaultRuntime(), store) 93 defer func() { 94 assert.NoError(t, s.Close()) 95 }() 96 97 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 98 defer cancel() 99 100 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 101 v := mustGetTestAsyncTask(t, store, 1)[0] 102 assert.NoError(t, s.Allocate(ctx, v, "r1")) 103 104 v = mustGetTestAsyncTask(t, store, 1)[0] 105 assert.Equal(t, task.TaskStatus_Running, v.Status) 106 assert.True(t, v.LastHeartbeat > 0) 107 assert.Equal(t, "r1", v.TaskRunner) 108 assert.Equal(t, uint32(1), v.Epoch) 109 } 110 111 func TestReAllocate(t *testing.T) { 112 store := NewMemTaskStorage() 113 s := NewTaskService(runtime.DefaultRuntime(), store) 114 defer func() { 115 assert.NoError(t, s.Close()) 116 }() 117 118 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 119 defer cancel() 120 121 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 122 v := mustGetTestAsyncTask(t, store, 1)[0] 123 assert.NoError(t, s.Allocate(ctx, v, "r1")) 124 125 v = mustGetTestAsyncTask(t, store, 1)[0] 126 assert.Equal(t, task.TaskStatus_Running, v.Status) 127 assert.True(t, v.LastHeartbeat > 0) 128 assert.Equal(t, "r1", v.TaskRunner) 129 assert.Equal(t, uint32(1), v.Epoch) 130 131 last := v.LastHeartbeat 132 time.Sleep(time.Millisecond) 133 assert.NoError(t, s.Allocate(ctx, v, "r2")) 134 v = mustGetTestAsyncTask(t, store, 1)[0] 135 assert.Equal(t, task.TaskStatus_Running, v.Status) 136 assert.True(t, v.LastHeartbeat > last) 137 assert.Equal(t, "r2", v.TaskRunner) 138 assert.Equal(t, uint32(2), v.Epoch) 139 } 140 141 func allocateWithNotExistTask(t *testing.T) { 142 store := NewMemTaskStorage() 143 s := NewTaskService(runtime.DefaultRuntime(), store) 144 defer func() { 145 assert.NoError(t, s.Close()) 146 }() 147 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 148 defer cancel() 149 _ = s.Allocate(ctx, task.AsyncTask{ID: 1}, "r1") 150 } 151 152 func TestAllocateWithNotExistTask(t *testing.T) { 153 if os.Getenv("RUN_TEST") == "1" { 154 allocateWithNotExistTask(t) 155 return 156 } 157 cmd := exec.Command(os.Args[0], "-test.run=TestAllocateWithNotExistTask") 158 cmd.Env = append(os.Environ(), "RUN_TEST=1") 159 err := cmd.Run() 160 // check Fatal is called 161 if e, ok := err.(*exec.ExitError); ok && !e.Success() { 162 return 163 } 164 t.Fatalf("process ran with err %v, want exit status 1", err) 165 } 166 167 func TestAllocateWithInvalidEpoch(t *testing.T) { 168 store := NewMemTaskStorage().(*memTaskStorage) 169 s := NewTaskService(runtime.DefaultRuntime(), store) 170 defer func() { 171 assert.NoError(t, s.Close()) 172 }() 173 174 store.preUpdate = func() { 175 store.Lock() 176 defer store.Unlock() 177 178 for k, v := range store.asyncTasks { 179 v.Epoch++ 180 store.asyncTasks[k] = v 181 } 182 } 183 184 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 185 defer cancel() 186 187 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 188 v := mustGetTestAsyncTask(t, store, 1)[0] 189 err := s.Allocate(ctx, v, "r2") 190 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrInvalidTask)) 191 } 192 193 func TestCompleted(t *testing.T) { 194 store := NewMemTaskStorage() 195 s := NewTaskService(runtime.DefaultRuntime(), store) 196 defer func() { 197 assert.NoError(t, s.Close()) 198 }() 199 200 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 201 defer cancel() 202 203 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 204 v := mustGetTestAsyncTask(t, store, 1)[0] 205 assert.NoError(t, s.Allocate(ctx, v, "r1")) 206 207 v = mustGetTestAsyncTask(t, store, 1)[0] 208 assert.NoError(t, s.Complete(ctx, "r1", v, 209 task.ExecuteResult{Code: task.ResultCode_Failed, Error: "error"})) 210 211 v = mustGetTestAsyncTask(t, store, 1)[0] 212 assert.Equal(t, task.TaskStatus_Completed, v.Status) 213 assert.Equal(t, task.ExecuteResult{Code: task.ResultCode_Failed, Error: "error"}, *v.ExecuteResult) 214 } 215 216 func TestCompletedWithInvalidStatus(t *testing.T) { 217 store := NewMemTaskStorage() 218 s := NewTaskService(runtime.DefaultRuntime(), store) 219 defer func() { 220 assert.NoError(t, s.Close()) 221 }() 222 223 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 224 defer cancel() 225 226 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 227 v := mustGetTestAsyncTask(t, store, 1)[0] 228 assert.NoError(t, s.Allocate(ctx, v, "r1")) 229 230 v = mustGetTestAsyncTask(t, store, 1)[0] 231 v.Status = task.TaskStatus_Created 232 mustUpdateTestAsyncTask(t, store, 1, []task.AsyncTask{v}) 233 234 err := s.Complete(ctx, "r1", v, 235 task.ExecuteResult{Code: task.ResultCode_Failed, Error: "error"}) 236 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrInvalidTask)) 237 } 238 239 func TestCompletedWithInvalidEpoch(t *testing.T) { 240 store := NewMemTaskStorage() 241 s := NewTaskService(runtime.DefaultRuntime(), store) 242 defer func() { 243 assert.NoError(t, s.Close()) 244 }() 245 246 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 247 defer cancel() 248 249 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 250 v := mustGetTestAsyncTask(t, store, 1)[0] 251 assert.NoError(t, s.Allocate(ctx, v, "r1")) 252 253 v = mustGetTestAsyncTask(t, store, 1)[0] 254 v.Epoch = 2 255 mustUpdateTestAsyncTask(t, store, 1, []task.AsyncTask{v}) 256 257 v.Epoch = 1 258 err := s.Complete(ctx, "r1", v, 259 task.ExecuteResult{Code: task.ResultCode_Failed, Error: "error"}) 260 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrInvalidTask)) 261 } 262 263 func TestCompletedWithInvalidTaskRunner(t *testing.T) { 264 store := NewMemTaskStorage() 265 s := NewTaskService(runtime.DefaultRuntime(), store) 266 defer func() { 267 assert.NoError(t, s.Close()) 268 }() 269 270 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 271 defer cancel() 272 273 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 274 v := mustGetTestAsyncTask(t, store, 1)[0] 275 assert.NoError(t, s.Allocate(ctx, v, "r1")) 276 277 v = mustGetTestAsyncTask(t, store, 1)[0] 278 err := s.Complete(ctx, "r2", v, 279 task.ExecuteResult{Code: task.ResultCode_Failed, Error: "error"}) 280 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrInvalidTask)) 281 } 282 283 func TestHeartbeat(t *testing.T) { 284 store := NewMemTaskStorage() 285 s := NewTaskService(runtime.DefaultRuntime(), store) 286 defer func() { 287 assert.NoError(t, s.Close()) 288 }() 289 290 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 291 defer cancel() 292 293 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 294 v := mustGetTestAsyncTask(t, store, 1)[0] 295 assert.NoError(t, s.Allocate(ctx, v, "r1")) 296 297 v = mustGetTestAsyncTask(t, store, 1)[0] 298 lastHeartbeat := v.LastHeartbeat 299 time.Sleep(time.Millisecond * 5) 300 assert.NoError(t, s.Heartbeat(ctx, v)) 301 302 v = mustGetTestAsyncTask(t, store, 1)[0] 303 assert.True(t, v.LastHeartbeat > lastHeartbeat) 304 } 305 306 func TestHeartbeatWithSmallEpoch(t *testing.T) { 307 store := NewMemTaskStorage() 308 s := NewTaskService(runtime.DefaultRuntime(), store) 309 defer func() { 310 assert.NoError(t, s.Close()) 311 }() 312 313 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 314 defer cancel() 315 316 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 317 v := mustGetTestAsyncTask(t, store, 1)[0] 318 assert.NoError(t, s.Allocate(ctx, v, "r1")) 319 320 v = mustGetTestAsyncTask(t, store, 1)[0] 321 v.Epoch = 2 322 mustUpdateTestAsyncTask(t, store, 1, []task.AsyncTask{v}) 323 324 v.Epoch = 1 325 err := s.Heartbeat(ctx, v) 326 assert.True(t, moerr.IsMoErrCode(err, moerr.ErrInvalidTask)) 327 } 328 329 func TestHeartbeatWithBiggerEpochShouldSuccess(t *testing.T) { 330 store := NewMemTaskStorage() 331 s := NewTaskService(runtime.DefaultRuntime(), store) 332 defer func() { 333 assert.NoError(t, s.Close()) 334 }() 335 336 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 337 defer cancel() 338 339 assert.NoError(t, s.CreateAsyncTask(ctx, newTestTaskMetadata("t1"))) 340 v := mustGetTestAsyncTask(t, store, 1)[0] 341 assert.NoError(t, s.Allocate(ctx, v, "r1")) 342 343 v = mustGetTestAsyncTask(t, store, 1)[0] 344 v.Epoch = 2 345 mustUpdateTestAsyncTask(t, store, 1, []task.AsyncTask{v}) 346 347 v.Epoch = 3 348 assert.NoError(t, s.Heartbeat(ctx, v)) 349 } 350 351 func TestCreateCronTask(t *testing.T) { 352 store := NewMemTaskStorage() 353 s := NewTaskService(runtime.DefaultRuntime(), store) 354 defer func() { 355 assert.NoError(t, s.Close()) 356 }() 357 358 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 359 defer cancel() 360 assert.NoError(t, s.CreateCronTask(ctx, newTestTaskMetadata("t1"), "* */5 * * * *")) 361 assert.NoError(t, s.CreateCronTask(ctx, newTestTaskMetadata("t1"), "* */5 * * * *")) 362 } 363 364 func TestQueryCronTask(t *testing.T) { 365 store := NewMemTaskStorage() 366 s := NewTaskService(runtime.DefaultRuntime(), store) 367 defer func() { 368 assert.NoError(t, s.Close()) 369 }() 370 371 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 372 defer cancel() 373 374 v1 := newTestCronTask("t1", "cron1") 375 v2 := newTestCronTask("t2", "cron2") 376 mustAddTestCronTask(t, store, 2, v1, v2) 377 378 v, err := s.QueryCronTask(ctx) 379 assert.NoError(t, err) 380 assert.Equal(t, 2, len(v)) 381 } 382 383 func TestQueryAsyncTask(t *testing.T) { 384 store := NewMemTaskStorage() 385 s := NewTaskService(runtime.DefaultRuntime(), store) 386 defer func() { 387 assert.NoError(t, s.Close()) 388 }() 389 390 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 391 defer cancel() 392 393 v1 := newTestAsyncTask("t1") 394 v2 := newTestAsyncTask("t2") 395 mustAddTestAsyncTask(t, store, 2, v1, v2) 396 397 v, err := s.QueryAsyncTask(ctx) 398 assert.NoError(t, err) 399 assert.Equal(t, 2, len(v)) 400 } 401 402 func newTestTaskMetadata(id string) task.TaskMetadata { 403 return task.TaskMetadata{ 404 ID: id, 405 } 406 } 407 408 func TestCreateDaemonTask(t *testing.T) { 409 store := NewMemTaskStorage() 410 s := NewTaskService(runtime.DefaultRuntime(), store) 411 defer func() { 412 assert.NoError(t, s.Close()) 413 }() 414 415 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 416 defer cancel() 417 assert.NoError(t, s.CreateDaemonTask(ctx, newTestTaskMetadata("t1"), 418 &task.Details{ 419 AccountID: 10, 420 Account: "a1", 421 Username: "u1", 422 Details: &task.Details_Connector{ 423 Connector: &task.ConnectorDetails{ 424 TableName: "d1.t1", 425 Options: map[string]string{ 426 "k1": "v1", 427 }, 428 }, 429 }, 430 })) 431 432 v := mustGetTestDaemonTask(t, store, 1)[0] 433 assert.Equal(t, uint64(0), v.ID) 434 assert.False(t, v.CreateAt.IsZero()) 435 assert.Equal(t, task.TaskStatus_Created, v.TaskStatus) 436 assert.Equal(t, "", v.TaskRunner) 437 assert.True(t, v.LastHeartbeat.IsZero()) 438 assert.Equal(t, newTestTaskMetadata("t1"), v.Metadata) 439 assert.Equal(t, task.TaskType_TypeKafkaSinkConnector, v.TaskType) 440 assert.Equal(t, uint32(10), v.Details.AccountID) 441 assert.Equal(t, "a1", v.Details.Account) 442 assert.Equal(t, "u1", v.Details.Username) 443 details, ok := v.Details.Details.(*task.Details_Connector) 444 assert.True(t, ok) 445 assert.Equal(t, "d1.t1", details.Connector.TableName) 446 assert.Equal(t, "v1", details.Connector.Options["k1"]) 447 } 448 449 func TestQueryDaemonTask(t *testing.T) { 450 store := NewMemTaskStorage() 451 s := NewTaskService(runtime.DefaultRuntime(), store) 452 defer func() { 453 assert.NoError(t, s.Close()) 454 }() 455 456 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 457 defer cancel() 458 459 v1 := newTestDaemonTask(1, "t1") 460 v2 := newTestDaemonTask(2, "t2") 461 mustAddTestDaemonTask(t, store, 2, v1, v2) 462 463 v, err := s.QueryDaemonTask(ctx) 464 assert.NoError(t, err) 465 assert.Equal(t, 2, len(v)) 466 } 467 468 func TestUpdateDaemonTaskTS(t *testing.T) { 469 store := NewMemTaskStorage() 470 s := NewTaskService(runtime.DefaultRuntime(), store) 471 defer func() { 472 assert.NoError(t, s.Close()) 473 }() 474 475 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 476 defer cancel() 477 478 v1 := newTestDaemonTask(1, "t1") 479 mustAddTestDaemonTask(t, store, 1, v1) 480 481 v1.TaskStatus = task.TaskStatus_Running 482 483 c, err := s.UpdateDaemonTask(ctx, []task.DaemonTask{v1}) 484 assert.NoError(t, err) 485 assert.Equal(t, 1, c) 486 487 ts, err := s.QueryDaemonTask(ctx) 488 assert.NoError(t, err) 489 assert.Equal(t, 1, len(ts)) 490 assert.Equal(t, task.TaskStatus_Running, ts[0].TaskStatus) 491 } 492 493 func TestHeartbeatDaemonTask(t *testing.T) { 494 store := NewMemTaskStorage() 495 s := NewTaskService(runtime.DefaultRuntime(), store) 496 defer func() { 497 assert.NoError(t, s.Close()) 498 }() 499 500 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 501 defer cancel() 502 503 v1 := newTestDaemonTask(1, "t1") 504 v1.TaskStatus = task.TaskStatus_Running 505 mustAddTestDaemonTask(t, store, 1, v1) 506 507 v1.LastHeartbeat = time.Now() 508 509 err := s.HeartbeatDaemonTask(ctx, v1) 510 assert.NoError(t, err) 511 512 ts, err := s.QueryDaemonTask(ctx) 513 assert.NoError(t, err) 514 assert.Equal(t, 1, len(ts)) 515 assert.False(t, ts[0].LastHeartbeat.IsZero()) 516 }