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  }