github.com/matrixorigin/matrixone@v1.2.0/pkg/taskservice/task_storage_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 "testing" 20 "time" 21 22 "github.com/matrixorigin/matrixone/pkg/common/runtime" 23 "github.com/matrixorigin/matrixone/pkg/pb/task" 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 ) 27 28 var ( 29 storages = map[string]func(*testing.T) TaskStorage{ 30 "mem": createMem, 31 "refresh": createRefresh, 32 } 33 ) 34 35 func createMem(t *testing.T) TaskStorage { 36 return NewMemTaskStorage() 37 } 38 39 func createRefresh(t *testing.T) TaskStorage { 40 return newRefreshableTaskStorage( 41 runtime.DefaultRuntime(), 42 func(context.Context, bool) (string, error) { return "", nil }, 43 NewFixedTaskStorageFactory(NewMemTaskStorage())) 44 } 45 46 // TODO: move to cluster testing. 47 // func createMysql(t *testing.T) TaskStorage { 48 // storage, err := NewMysqlTaskStorage("root:root@tcp(127.0.0.1:12345)/", "mo_task") 49 // require.NoError(t, err) 50 // return storage 51 // } 52 53 func TestAddAsyncTask(t *testing.T) { 54 for name, factory := range storages { 55 t.Run(name, func(t *testing.T) { 56 s := factory(t) 57 defer func() { 58 assert.NoError(t, s.Close()) 59 }() 60 61 v := newTestAsyncTask("t1") 62 mustAddTestAsyncTask(t, s, 1, v) 63 mustAddTestAsyncTask(t, s, 0, v) 64 assert.Equal(t, 1, len(mustGetTestAsyncTask(t, s, 1))) 65 }) 66 } 67 } 68 69 func TestUpdateAsyncTask(t *testing.T) { 70 for name, factory := range storages { 71 t.Run(name, func(t *testing.T) { 72 s := factory(t) 73 defer func() { 74 assert.NoError(t, s.Close()) 75 }() 76 77 v := newTestAsyncTask("t1") 78 mustAddTestAsyncTask(t, s, 1, v) 79 80 tasks := mustGetTestAsyncTask(t, s, 1) 81 tasks[0].Metadata.Executor = 1 82 mustUpdateTestAsyncTask(t, s, 1, tasks) 83 }) 84 } 85 } 86 87 func TestUpdateAsyncTaskWithConditions(t *testing.T) { 88 for name, factory := range storages { 89 t.Run(name, func(t *testing.T) { 90 s := factory(t) 91 defer func() { 92 assert.NoError(t, s.Close()) 93 }() 94 95 mustAddTestAsyncTask(t, s, 1, newTestAsyncTask("t1")) 96 tasks := mustGetTestAsyncTask(t, s, 1) 97 98 mustUpdateTestAsyncTask(t, s, 0, tasks, WithTaskRunnerCond(EQ, "t2")) 99 mustUpdateTestAsyncTask(t, s, 1, tasks, WithTaskRunnerCond(EQ, "t1")) 100 101 tasks[0].Metadata.Context = []byte{1} 102 mustUpdateTestAsyncTask(t, s, 0, tasks, WithTaskIDCond(EQ, tasks[0].ID+1)) 103 mustUpdateTestAsyncTask(t, s, 1, tasks, WithTaskIDCond(EQ, tasks[0].ID)) 104 tasks[0].Metadata.Context = []byte{1, 2} 105 mustUpdateTestAsyncTask(t, s, 1, tasks, WithTaskIDCond(GT, 0)) 106 }) 107 } 108 } 109 110 func TestDeleteAsyncTaskWithConditions(t *testing.T) { 111 for name, factory := range storages { 112 t.Run(name, func(t *testing.T) { 113 s := factory(t) 114 defer func() { 115 assert.NoError(t, s.Close()) 116 }() 117 118 mustAddTestAsyncTask(t, s, 1, newTestAsyncTask("t1")) 119 mustAddTestAsyncTask(t, s, 1, newTestAsyncTask("t2")) 120 mustAddTestAsyncTask(t, s, 1, newTestAsyncTask("t3")) 121 tasks := mustGetTestAsyncTask(t, s, 3) 122 123 mustDeleteTestAsyncTask(t, s, 0, WithTaskRunnerCond(EQ, "t4")) 124 mustDeleteTestAsyncTask(t, s, 1, WithTaskRunnerCond(EQ, "t1")) 125 126 mustDeleteTestAsyncTask(t, s, 0, WithTaskIDCond(EQ, tasks[len(tasks)-1].ID+1)) 127 mustDeleteTestAsyncTask(t, s, 2, WithTaskIDCond(GT, tasks[0].ID)) 128 129 mustGetTestAsyncTask(t, s, 0) 130 }) 131 } 132 } 133 134 func TestQueryAsyncTaskWithConditions(t *testing.T) { 135 for name, factory := range storages { 136 t.Run(name, func(t *testing.T) { 137 s := factory(t) 138 defer func() { 139 assert.NoError(t, s.Close()) 140 }() 141 142 mustAddTestAsyncTask(t, s, 1, newTestAsyncTask("t1")) 143 mustAddTestAsyncTask(t, s, 1, newTestAsyncTask("t2")) 144 mustAddTestAsyncTask(t, s, 1, newTestAsyncTask("t3")) 145 tasks := mustGetTestAsyncTask(t, s, 3) 146 147 mustGetTestAsyncTask(t, s, 1, WithLimitCond(1)) 148 mustGetTestAsyncTask(t, s, 1, WithTaskRunnerCond(EQ, "t1")) 149 mustGetTestAsyncTask(t, s, 2, WithTaskIDCond(GT, tasks[0].ID)) 150 mustGetTestAsyncTask(t, s, 3, WithTaskIDCond(GE, tasks[0].ID)) 151 mustGetTestAsyncTask(t, s, 3, WithTaskIDCond(LE, tasks[2].ID)) 152 mustGetTestAsyncTask(t, s, 2, WithTaskIDCond(LT, tasks[2].ID)) 153 mustGetTestAsyncTask(t, s, 1, WithLimitCond(1), WithTaskIDCond(GT, tasks[0].ID)) 154 mustGetTestAsyncTask(t, s, 1, WithTaskIDCond(EQ, tasks[0].ID)) 155 }) 156 } 157 } 158 159 func TestAddAndQueryCronTask(t *testing.T) { 160 for name, factory := range storages { 161 t.Run(name, func(t *testing.T) { 162 s := factory(t) 163 defer func() { 164 assert.NoError(t, s.Close()) 165 }() 166 167 mustQueryTestCronTask(t, s, 0) 168 169 v1 := newTestCronTask("t1", "cron1") 170 v2 := newTestCronTask("t2", "cron2") 171 mustAddTestCronTask(t, s, 2, v1, v2) 172 mustQueryTestCronTask(t, s, 2) 173 174 mustAddTestCronTask(t, s, 0, v1, v2) 175 mustQueryTestCronTask(t, s, 2) 176 }) 177 } 178 } 179 180 func TestUpdateCronTask(t *testing.T) { 181 for name, factory := range storages { 182 t.Run(name, func(t *testing.T) { 183 s := factory(t) 184 defer func() { 185 assert.NoError(t, s.Close()) 186 }() 187 188 v1 := newTestCronTask("t1", "cron1") 189 v2 := newTestAsyncTask("t1-cron-1") 190 v3 := newTestAsyncTask("t1-cron-2") 191 192 ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10) 193 defer cancel() 194 195 n, err := s.UpdateCronTask(ctx, v1, v2) 196 assert.NoError(t, err) 197 assert.Equal(t, 0, n) 198 199 mustAddTestCronTask(t, s, 1, v1) 200 mustAddTestAsyncTask(t, s, 1, v2) 201 202 v1 = mustQueryTestCronTask(t, s, 1)[0] 203 204 n, err = s.UpdateCronTask(ctx, v1, v2) 205 assert.NoError(t, err) 206 assert.Equal(t, 0, n) 207 208 n, err = s.UpdateCronTask(ctx, v1, v3) 209 assert.NoError(t, err) 210 assert.Equal(t, 0, n) 211 212 v1.TriggerTimes++ 213 n, err = s.UpdateCronTask(ctx, v1, v3) 214 assert.NoError(t, err) 215 assert.Equal(t, 2, n) 216 }) 217 } 218 } 219 220 func TestAddDaemonTask(t *testing.T) { 221 for name, factory := range storages { 222 t.Run(name, func(t *testing.T) { 223 s := factory(t) 224 defer func() { 225 assert.NoError(t, s.Close()) 226 }() 227 228 v := newTestDaemonTask(1, "t1") 229 mustAddTestDaemonTask(t, s, 1, v) 230 mustAddTestDaemonTask(t, s, 0, v) 231 assert.Equal(t, 1, len(mustGetTestDaemonTask(t, s, 1))) 232 }) 233 } 234 } 235 236 func TestUpdateDaemonTask(t *testing.T) { 237 for name, factory := range storages { 238 t.Run(name, func(t *testing.T) { 239 s := factory(t) 240 defer func() { 241 assert.NoError(t, s.Close()) 242 }() 243 244 v := newTestDaemonTask(1, "t1") 245 mustAddTestDaemonTask(t, s, 1, v) 246 247 tasks := mustGetTestDaemonTask(t, s, 1) 248 tasks[0].Metadata.Executor = 1 249 mustUpdateTestDaemonTask(t, s, 1, tasks) 250 }) 251 } 252 } 253 254 func TestUpdateDaemonTaskWithConditions(t *testing.T) { 255 for name, factory := range storages { 256 t.Run(name, func(t *testing.T) { 257 s := factory(t) 258 defer func() { 259 assert.NoError(t, s.Close()) 260 }() 261 262 mustAddTestDaemonTask(t, s, 1, newTestDaemonTask(1, "t1")) 263 tasks := mustGetTestDaemonTask(t, s, 1) 264 265 mustUpdateTestDaemonTask(t, s, 0, tasks, WithTaskRunnerCond(EQ, "t2")) 266 mustUpdateTestDaemonTask(t, s, 1, tasks, WithTaskRunnerCond(EQ, "t1")) 267 268 tasks[0].Metadata.Context = []byte{1} 269 mustUpdateTestDaemonTask(t, s, 0, tasks, WithTaskIDCond(EQ, tasks[0].ID+1)) 270 mustUpdateTestDaemonTask(t, s, 1, tasks, WithTaskIDCond(EQ, tasks[0].ID)) 271 tasks[0].Metadata.Context = []byte{1, 2} 272 mustUpdateTestDaemonTask(t, s, 1, tasks, WithTaskIDCond(GT, 0)) 273 }) 274 } 275 } 276 277 func TestDeleteDaemonTaskWithConditions(t *testing.T) { 278 for name, factory := range storages { 279 t.Run(name, func(t *testing.T) { 280 s := factory(t) 281 defer func() { 282 assert.NoError(t, s.Close()) 283 }() 284 285 mustAddTestDaemonTask(t, s, 1, newTestDaemonTask(1, "t1")) 286 mustAddTestDaemonTask(t, s, 1, newTestDaemonTask(2, "t2")) 287 mustAddTestDaemonTask(t, s, 1, newTestDaemonTask(3, "t3")) 288 tasks := mustGetTestDaemonTask(t, s, 3) 289 290 mustDeleteTestDaemonTask(t, s, 0, WithTaskRunnerCond(EQ, "t4")) 291 mustDeleteTestDaemonTask(t, s, 1, WithTaskRunnerCond(EQ, "t1")) 292 293 mustDeleteTestDaemonTask(t, s, 0, WithTaskIDCond(EQ, tasks[len(tasks)-1].ID+1)) 294 mustDeleteTestDaemonTask(t, s, 2, WithTaskIDCond(GT, tasks[0].ID)) 295 296 mustGetTestDaemonTask(t, s, 0) 297 }) 298 } 299 } 300 301 func TestQueryDaemonTaskWithConditions(t *testing.T) { 302 for name, factory := range storages { 303 t.Run(name, func(t *testing.T) { 304 s := factory(t) 305 defer func() { 306 assert.NoError(t, s.Close()) 307 }() 308 309 mustAddTestDaemonTask(t, s, 1, newTestDaemonTask(1, "t1")) 310 mustAddTestDaemonTask(t, s, 1, newTestDaemonTask(2, "t2")) 311 mustAddTestDaemonTask(t, s, 1, newTestDaemonTask(3, "t3")) 312 tasks := mustGetTestDaemonTask(t, s, 3) 313 314 mustGetTestDaemonTask(t, s, 1, WithLimitCond(1)) 315 mustGetTestDaemonTask(t, s, 1, WithTaskRunnerCond(EQ, "t1")) 316 mustGetTestDaemonTask(t, s, 2, WithTaskIDCond(GT, tasks[0].ID)) 317 mustGetTestDaemonTask(t, s, 3, WithTaskIDCond(GE, tasks[0].ID)) 318 mustGetTestDaemonTask(t, s, 3, WithTaskIDCond(LE, tasks[2].ID)) 319 mustGetTestDaemonTask(t, s, 2, WithTaskIDCond(LT, tasks[2].ID)) 320 mustGetTestDaemonTask(t, s, 1, WithLimitCond(1), WithTaskIDCond(GT, tasks[0].ID)) 321 mustGetTestDaemonTask(t, s, 1, WithTaskIDCond(EQ, tasks[0].ID)) 322 }) 323 } 324 } 325 326 func mustGetTestAsyncTask(t *testing.T, s TaskStorage, expectCount int, conds ...Condition) []task.AsyncTask { 327 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 328 defer cancel() 329 tasks, err := s.QueryAsyncTask(ctx, conds...) 330 require.NoError(t, err) 331 require.Equal(t, expectCount, len(tasks)) 332 return tasks 333 } 334 335 func mustAddTestAsyncTask(t *testing.T, s TaskStorage, expectAdded int, tasks ...task.AsyncTask) { 336 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 337 defer cancel() 338 339 n, err := s.AddAsyncTask(ctx, tasks...) 340 require.NoError(t, err) 341 require.Equal(t, expectAdded, n) 342 } 343 344 func mustUpdateTestAsyncTask(t *testing.T, s TaskStorage, expectUpdated int, tasks []task.AsyncTask, conds ...Condition) { 345 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 346 defer cancel() 347 348 n, err := s.UpdateAsyncTask(ctx, tasks, conds...) 349 require.NoError(t, err) 350 require.Equal(t, expectUpdated, n) 351 } 352 353 func mustDeleteTestAsyncTask(t *testing.T, s TaskStorage, expectUpdated int, conds ...Condition) { 354 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 355 defer cancel() 356 357 n, err := s.DeleteAsyncTask(ctx, conds...) 358 require.NoError(t, err) 359 require.Equal(t, expectUpdated, n) 360 } 361 362 func mustAddTestCronTask(t *testing.T, s TaskStorage, expectAdded int, tasks ...task.CronTask) { 363 ctx, cancel := context.WithTimeout(context.Background(), time.Second*1000) 364 defer cancel() 365 366 n, err := s.AddCronTask(ctx, tasks...) 367 require.NoError(t, err) 368 require.Equal(t, expectAdded, n) 369 } 370 371 func mustQueryTestCronTask(t *testing.T, s TaskStorage, expectQueryCount int) []task.CronTask { 372 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 373 defer cancel() 374 375 tasks, err := s.QueryCronTask(ctx) 376 require.NoError(t, err) 377 require.Equal(t, expectQueryCount, len(tasks)) 378 return tasks 379 } 380 381 func mustAddTestDaemonTask(t *testing.T, s TaskStorage, expectAdded int, tasks ...task.DaemonTask) { 382 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 383 defer cancel() 384 385 n, err := s.AddDaemonTask(ctx, tasks...) 386 require.NoError(t, err) 387 require.Equal(t, expectAdded, n) 388 } 389 390 func mustGetTestDaemonTask(t *testing.T, s TaskStorage, expectCount int, conds ...Condition) []task.DaemonTask { 391 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 392 defer cancel() 393 tasks, err := s.QueryDaemonTask(ctx, conds...) 394 require.NoError(t, err) 395 require.Equal(t, expectCount, len(tasks)) 396 return tasks 397 } 398 399 func mustUpdateTestDaemonTask(t *testing.T, s TaskStorage, expectUpdated int, tasks []task.DaemonTask, conds ...Condition) { 400 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 401 defer cancel() 402 403 n, err := s.UpdateDaemonTask(ctx, tasks, conds...) 404 require.NoError(t, err) 405 require.Equal(t, expectUpdated, n) 406 } 407 408 func mustDeleteTestDaemonTask(t *testing.T, s TaskStorage, expectUpdated int, conds ...Condition) { 409 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 410 defer cancel() 411 412 n, err := s.DeleteDaemonTask(ctx, conds...) 413 require.NoError(t, err) 414 require.Equal(t, expectUpdated, n) 415 } 416 417 func newTestAsyncTask(id string) task.AsyncTask { 418 v := task.AsyncTask{} 419 v.Metadata.ID = id 420 v.TaskRunner = id 421 return v 422 } 423 424 func newTestCronTask(id, cron string) task.CronTask { 425 v := task.CronTask{} 426 v.Metadata.ID = id 427 v.CronExpr = cron 428 return v 429 } 430 431 func newTestDaemonTask(id uint64, mid string) task.DaemonTask { 432 v := task.DaemonTask{} 433 v.ID = id 434 v.Metadata.ID = mid 435 v.TaskRunner = mid 436 return v 437 }