github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/store/storetest/job_store.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package storetest
     5  
     6  import (
     7  	"testing"
     8  
     9  	"time"
    10  
    11  	"github.com/mattermost/mattermost-server/v5/model"
    12  	"github.com/mattermost/mattermost-server/v5/store"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestJobStore(t *testing.T, ss store.Store) {
    18  	t.Run("JobSaveGet", func(t *testing.T) { testJobSaveGet(t, ss) })
    19  	t.Run("JobGetAllByType", func(t *testing.T) { testJobGetAllByType(t, ss) })
    20  	t.Run("JobGetAllByTypePage", func(t *testing.T) { testJobGetAllByTypePage(t, ss) })
    21  	t.Run("JobGetAllPage", func(t *testing.T) { testJobGetAllPage(t, ss) })
    22  	t.Run("JobGetAllByStatus", func(t *testing.T) { testJobGetAllByStatus(t, ss) })
    23  	t.Run("GetNewestJobByStatusAndType", func(t *testing.T) { testJobStoreGetNewestJobByStatusAndType(t, ss) })
    24  	t.Run("GetCountByStatusAndType", func(t *testing.T) { testJobStoreGetCountByStatusAndType(t, ss) })
    25  	t.Run("JobUpdateOptimistically", func(t *testing.T) { testJobUpdateOptimistically(t, ss) })
    26  	t.Run("JobUpdateStatusUpdateStatusOptimistically", func(t *testing.T) { testJobUpdateStatusUpdateStatusOptimistically(t, ss) })
    27  	t.Run("JobDelete", func(t *testing.T) { testJobDelete(t, ss) })
    28  }
    29  
    30  func testJobSaveGet(t *testing.T, ss store.Store) {
    31  	job := &model.Job{
    32  		Id:     model.NewId(),
    33  		Type:   model.NewId(),
    34  		Status: model.NewId(),
    35  		Data: map[string]string{
    36  			"Processed":     "0",
    37  			"Total":         "12345",
    38  			"LastProcessed": "abcd",
    39  		},
    40  	}
    41  
    42  	_, err := ss.Job().Save(job)
    43  	require.Nil(t, err)
    44  
    45  	defer ss.Job().Delete(job.Id)
    46  
    47  	received, err := ss.Job().Get(job.Id)
    48  	require.Nil(t, err)
    49  	require.Equal(t, job.Id, received.Id, "received incorrect job after save")
    50  	require.Equal(t, "12345", received.Data["Total"])
    51  }
    52  
    53  func testJobGetAllByType(t *testing.T, ss store.Store) {
    54  	jobType := model.NewId()
    55  
    56  	jobs := []*model.Job{
    57  		{
    58  			Id:   model.NewId(),
    59  			Type: jobType,
    60  		},
    61  		{
    62  			Id:   model.NewId(),
    63  			Type: jobType,
    64  		},
    65  		{
    66  			Id:   model.NewId(),
    67  			Type: model.NewId(),
    68  		},
    69  	}
    70  
    71  	for _, job := range jobs {
    72  		_, err := ss.Job().Save(job)
    73  		require.Nil(t, err)
    74  		defer ss.Job().Delete(job.Id)
    75  	}
    76  
    77  	received, err := ss.Job().GetAllByType(jobType)
    78  	require.Nil(t, err)
    79  	require.Len(t, received, 2)
    80  	require.ElementsMatch(t, []string{jobs[0].Id, jobs[1].Id}, []string{received[0].Id, received[1].Id})
    81  }
    82  
    83  func testJobGetAllByTypePage(t *testing.T, ss store.Store) {
    84  	jobType := model.NewId()
    85  
    86  	jobs := []*model.Job{
    87  		{
    88  			Id:       model.NewId(),
    89  			Type:     jobType,
    90  			CreateAt: 1000,
    91  		},
    92  		{
    93  			Id:       model.NewId(),
    94  			Type:     jobType,
    95  			CreateAt: 999,
    96  		},
    97  		{
    98  			Id:       model.NewId(),
    99  			Type:     jobType,
   100  			CreateAt: 1001,
   101  		},
   102  		{
   103  			Id:       model.NewId(),
   104  			Type:     model.NewId(),
   105  			CreateAt: 1002,
   106  		},
   107  	}
   108  
   109  	for _, job := range jobs {
   110  		_, err := ss.Job().Save(job)
   111  		require.Nil(t, err)
   112  		defer ss.Job().Delete(job.Id)
   113  	}
   114  
   115  	received, err := ss.Job().GetAllByTypePage(jobType, 0, 2)
   116  	require.Nil(t, err)
   117  	require.Len(t, received, 2)
   118  	require.Equal(t, received[0].Id, jobs[2].Id, "should've received newest job first")
   119  	require.Equal(t, received[1].Id, jobs[0].Id, "should've received second newest job second")
   120  
   121  	received, err = ss.Job().GetAllByTypePage(jobType, 2, 2)
   122  	require.Nil(t, err)
   123  	require.Len(t, received, 1)
   124  	require.Equal(t, received[0].Id, jobs[1].Id, "should've received oldest job last")
   125  }
   126  
   127  func testJobGetAllPage(t *testing.T, ss store.Store) {
   128  	jobType := model.NewId()
   129  	createAtTime := model.GetMillis()
   130  
   131  	jobs := []*model.Job{
   132  		{
   133  			Id:       model.NewId(),
   134  			Type:     jobType,
   135  			CreateAt: createAtTime + 1,
   136  		},
   137  		{
   138  			Id:       model.NewId(),
   139  			Type:     jobType,
   140  			CreateAt: createAtTime,
   141  		},
   142  		{
   143  			Id:       model.NewId(),
   144  			Type:     jobType,
   145  			CreateAt: createAtTime + 2,
   146  		},
   147  	}
   148  
   149  	for _, job := range jobs {
   150  		_, err := ss.Job().Save(job)
   151  		require.Nil(t, err)
   152  		defer ss.Job().Delete(job.Id)
   153  	}
   154  
   155  	received, err := ss.Job().GetAllPage(0, 2)
   156  	require.Nil(t, err)
   157  	require.Len(t, received, 2)
   158  	require.Equal(t, received[0].Id, jobs[2].Id, "should've received newest job first")
   159  	require.Equal(t, received[1].Id, jobs[0].Id, "should've received second newest job second")
   160  
   161  	received, err = ss.Job().GetAllPage(2, 2)
   162  	require.Nil(t, err)
   163  	require.NotEmpty(t, received)
   164  	require.Equal(t, received[0].Id, jobs[1].Id, "should've received oldest job last")
   165  }
   166  
   167  func testJobGetAllByStatus(t *testing.T, ss store.Store) {
   168  	jobType := model.NewId()
   169  	status := model.NewId()
   170  
   171  	jobs := []*model.Job{
   172  		{
   173  			Id:       model.NewId(),
   174  			Type:     jobType,
   175  			CreateAt: 1000,
   176  			Status:   status,
   177  			Data: map[string]string{
   178  				"test": "data",
   179  			},
   180  		},
   181  		{
   182  			Id:       model.NewId(),
   183  			Type:     jobType,
   184  			CreateAt: 999,
   185  			Status:   status,
   186  		},
   187  		{
   188  			Id:       model.NewId(),
   189  			Type:     jobType,
   190  			CreateAt: 1001,
   191  			Status:   status,
   192  		},
   193  		{
   194  			Id:       model.NewId(),
   195  			Type:     jobType,
   196  			CreateAt: 1002,
   197  			Status:   model.NewId(),
   198  		},
   199  	}
   200  
   201  	for _, job := range jobs {
   202  		_, err := ss.Job().Save(job)
   203  		require.Nil(t, err)
   204  		defer ss.Job().Delete(job.Id)
   205  	}
   206  
   207  	received, err := ss.Job().GetAllByStatus(status)
   208  	require.Nil(t, err)
   209  	require.Len(t, received, 3)
   210  	require.Equal(t, received[0].Id, jobs[1].Id)
   211  	require.Equal(t, received[1].Id, jobs[0].Id)
   212  	require.Equal(t, received[2].Id, jobs[2].Id)
   213  	require.Equal(t, "data", received[1].Data["test"], "should've received job data field back as saved")
   214  }
   215  
   216  func testJobStoreGetNewestJobByStatusAndType(t *testing.T, ss store.Store) {
   217  	jobType1 := model.NewId()
   218  	jobType2 := model.NewId()
   219  	status1 := model.NewId()
   220  	status2 := model.NewId()
   221  
   222  	jobs := []*model.Job{
   223  		{
   224  			Id:       model.NewId(),
   225  			Type:     jobType1,
   226  			CreateAt: 1001,
   227  			Status:   status1,
   228  		},
   229  		{
   230  			Id:       model.NewId(),
   231  			Type:     jobType1,
   232  			CreateAt: 1000,
   233  			Status:   status1,
   234  		},
   235  		{
   236  			Id:       model.NewId(),
   237  			Type:     jobType2,
   238  			CreateAt: 1003,
   239  			Status:   status1,
   240  		},
   241  		{
   242  			Id:       model.NewId(),
   243  			Type:     jobType1,
   244  			CreateAt: 1004,
   245  			Status:   status2,
   246  		},
   247  	}
   248  
   249  	for _, job := range jobs {
   250  		_, err := ss.Job().Save(job)
   251  		require.Nil(t, err)
   252  		defer ss.Job().Delete(job.Id)
   253  	}
   254  
   255  	received, err := ss.Job().GetNewestJobByStatusAndType(status1, jobType1)
   256  	assert.Nil(t, err)
   257  	assert.EqualValues(t, jobs[0].Id, received.Id)
   258  
   259  	received, err = ss.Job().GetNewestJobByStatusAndType(model.NewId(), model.NewId())
   260  	assert.Nil(t, err)
   261  	assert.Nil(t, received)
   262  }
   263  
   264  func testJobStoreGetCountByStatusAndType(t *testing.T, ss store.Store) {
   265  	jobType1 := model.NewId()
   266  	jobType2 := model.NewId()
   267  	status1 := model.NewId()
   268  	status2 := model.NewId()
   269  
   270  	jobs := []*model.Job{
   271  		{
   272  			Id:       model.NewId(),
   273  			Type:     jobType1,
   274  			CreateAt: 1000,
   275  			Status:   status1,
   276  		},
   277  		{
   278  			Id:       model.NewId(),
   279  			Type:     jobType1,
   280  			CreateAt: 999,
   281  			Status:   status1,
   282  		},
   283  		{
   284  			Id:       model.NewId(),
   285  			Type:     jobType2,
   286  			CreateAt: 1001,
   287  			Status:   status1,
   288  		},
   289  		{
   290  			Id:       model.NewId(),
   291  			Type:     jobType1,
   292  			CreateAt: 1002,
   293  			Status:   status2,
   294  		},
   295  	}
   296  
   297  	for _, job := range jobs {
   298  		_, err := ss.Job().Save(job)
   299  		require.Nil(t, err)
   300  		defer ss.Job().Delete(job.Id)
   301  	}
   302  
   303  	count, err := ss.Job().GetCountByStatusAndType(status1, jobType1)
   304  	assert.Nil(t, err)
   305  	assert.EqualValues(t, 2, count)
   306  
   307  	count, err = ss.Job().GetCountByStatusAndType(status2, jobType2)
   308  	assert.Nil(t, err)
   309  	assert.EqualValues(t, 0, count)
   310  
   311  	count, err = ss.Job().GetCountByStatusAndType(status1, jobType2)
   312  	assert.Nil(t, err)
   313  	assert.EqualValues(t, 1, count)
   314  
   315  	count, err = ss.Job().GetCountByStatusAndType(status2, jobType1)
   316  	assert.Nil(t, err)
   317  	assert.EqualValues(t, 1, count)
   318  }
   319  
   320  func testJobUpdateOptimistically(t *testing.T, ss store.Store) {
   321  	job := &model.Job{
   322  		Id:       model.NewId(),
   323  		Type:     model.JOB_TYPE_DATA_RETENTION,
   324  		CreateAt: model.GetMillis(),
   325  		Status:   model.JOB_STATUS_PENDING,
   326  	}
   327  
   328  	_, err := ss.Job().Save(job)
   329  	require.Nil(t, err)
   330  	defer ss.Job().Delete(job.Id)
   331  
   332  	job.LastActivityAt = model.GetMillis()
   333  	job.Status = model.JOB_STATUS_IN_PROGRESS
   334  	job.Progress = 50
   335  	job.Data = map[string]string{
   336  		"Foo": "Bar",
   337  	}
   338  
   339  	updated, err := ss.Job().UpdateOptimistically(job, model.JOB_STATUS_SUCCESS)
   340  	require.False(t, err != nil && updated)
   341  
   342  	time.Sleep(2 * time.Millisecond)
   343  
   344  	updated, err = ss.Job().UpdateOptimistically(job, model.JOB_STATUS_PENDING)
   345  	require.Nil(t, err)
   346  	require.True(t, updated)
   347  
   348  	updatedJob, err := ss.Job().Get(job.Id)
   349  	require.Nil(t, err)
   350  
   351  	require.Equal(t, updatedJob.Type, job.Type)
   352  	require.Equal(t, updatedJob.CreateAt, job.CreateAt)
   353  	require.Equal(t, updatedJob.Status, job.Status)
   354  	require.Greater(t, updatedJob.LastActivityAt, job.LastActivityAt)
   355  	require.Equal(t, updatedJob.Progress, job.Progress)
   356  	require.Equal(t, updatedJob.Data["Foo"], job.Data["Foo"])
   357  }
   358  
   359  func testJobUpdateStatusUpdateStatusOptimistically(t *testing.T, ss store.Store) {
   360  	job := &model.Job{
   361  		Id:       model.NewId(),
   362  		Type:     model.JOB_TYPE_DATA_RETENTION,
   363  		CreateAt: model.GetMillis(),
   364  		Status:   model.JOB_STATUS_SUCCESS,
   365  	}
   366  
   367  	var lastUpdateAt int64
   368  	received, err := ss.Job().Save(job)
   369  	require.Nil(t, err)
   370  	lastUpdateAt = received.LastActivityAt
   371  
   372  	defer ss.Job().Delete(job.Id)
   373  
   374  	time.Sleep(2 * time.Millisecond)
   375  
   376  	received, err = ss.Job().UpdateStatus(job.Id, model.JOB_STATUS_PENDING)
   377  	require.Nil(t, err)
   378  
   379  	require.Equal(t, model.JOB_STATUS_PENDING, received.Status)
   380  	require.Greater(t, received.LastActivityAt, lastUpdateAt)
   381  	lastUpdateAt = received.LastActivityAt
   382  
   383  	time.Sleep(2 * time.Millisecond)
   384  
   385  	updated, err := ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_IN_PROGRESS, model.JOB_STATUS_SUCCESS)
   386  	require.Nil(t, err)
   387  	require.False(t, updated)
   388  
   389  	received, err = ss.Job().Get(job.Id)
   390  	require.Nil(t, err)
   391  
   392  	require.Equal(t, model.JOB_STATUS_PENDING, received.Status)
   393  	require.Equal(t, received.LastActivityAt, lastUpdateAt)
   394  
   395  	time.Sleep(2 * time.Millisecond)
   396  
   397  	updated, err = ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_PENDING, model.JOB_STATUS_IN_PROGRESS)
   398  	require.Nil(t, err)
   399  	require.True(t, updated, "should have succeeded")
   400  
   401  	var startAtSet int64
   402  	received, err = ss.Job().Get(job.Id)
   403  	require.Nil(t, err)
   404  	require.Equal(t, model.JOB_STATUS_IN_PROGRESS, received.Status)
   405  	require.NotEqual(t, 0, received.StartAt)
   406  	require.Greater(t, received.LastActivityAt, lastUpdateAt)
   407  	lastUpdateAt = received.LastActivityAt
   408  	startAtSet = received.StartAt
   409  
   410  	time.Sleep(2 * time.Millisecond)
   411  
   412  	updated, err = ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_IN_PROGRESS, model.JOB_STATUS_SUCCESS)
   413  	require.Nil(t, err)
   414  	require.True(t, updated, "should have succeeded")
   415  
   416  	received, err = ss.Job().Get(job.Id)
   417  	require.Nil(t, err)
   418  	require.Equal(t, model.JOB_STATUS_SUCCESS, received.Status)
   419  	require.Equal(t, startAtSet, received.StartAt)
   420  	require.Greater(t, received.LastActivityAt, lastUpdateAt)
   421  }
   422  
   423  func testJobDelete(t *testing.T, ss store.Store) {
   424  	job, err := ss.Job().Save(&model.Job{Id: model.NewId()})
   425  	require.Nil(t, err)
   426  
   427  	_, err = ss.Job().Delete(job.Id)
   428  	assert.Nil(t, err)
   429  }