github.com/mad-app/mattermost-server@v5.11.1+incompatible/store/storetest/job_store.go (about)

     1  // Copyright (c) 2017-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/model"
    12  	"github.com/mattermost/mattermost-server/store"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  func TestJobStore(t *testing.T, ss store.Store) {
    17  	t.Run("JobSaveGet", func(t *testing.T) { testJobSaveGet(t, ss) })
    18  	t.Run("JobGetAllByType", func(t *testing.T) { testJobGetAllByType(t, ss) })
    19  	t.Run("JobGetAllByTypePage", func(t *testing.T) { testJobGetAllByTypePage(t, ss) })
    20  	t.Run("JobGetAllPage", func(t *testing.T) { testJobGetAllPage(t, ss) })
    21  	t.Run("JobGetAllByStatus", func(t *testing.T) { testJobGetAllByStatus(t, ss) })
    22  	t.Run("GetNewestJobByStatusAndType", func(t *testing.T) { testJobStoreGetNewestJobByStatusAndType(t, ss) })
    23  	t.Run("GetCountByStatusAndType", func(t *testing.T) { testJobStoreGetCountByStatusAndType(t, ss) })
    24  	t.Run("JobUpdateOptimistically", func(t *testing.T) { testJobUpdateOptimistically(t, ss) })
    25  	t.Run("JobUpdateStatusUpdateStatusOptimistically", func(t *testing.T) { testJobUpdateStatusUpdateStatusOptimistically(t, ss) })
    26  	t.Run("JobDelete", func(t *testing.T) { testJobDelete(t, ss) })
    27  }
    28  
    29  func testJobSaveGet(t *testing.T, ss store.Store) {
    30  	job := &model.Job{
    31  		Id:     model.NewId(),
    32  		Type:   model.NewId(),
    33  		Status: model.NewId(),
    34  		Data: map[string]string{
    35  			"Processed":     "0",
    36  			"Total":         "12345",
    37  			"LastProcessed": "abcd",
    38  		},
    39  	}
    40  
    41  	if result := <-ss.Job().Save(job); result.Err != nil {
    42  		t.Fatal(result.Err)
    43  	}
    44  
    45  	defer func() {
    46  		<-ss.Job().Delete(job.Id)
    47  	}()
    48  
    49  	if result := <-ss.Job().Get(job.Id); result.Err != nil {
    50  		t.Fatal(result.Err)
    51  	} else if received := result.Data.(*model.Job); received.Id != job.Id {
    52  		t.Fatal("received incorrect job after save")
    53  	} else if received.Data["Total"] != "12345" {
    54  		t.Fatal("data field was not retrieved successfully:", received.Data)
    55  	}
    56  }
    57  
    58  func testJobGetAllByType(t *testing.T, ss store.Store) {
    59  	jobType := model.NewId()
    60  
    61  	jobs := []*model.Job{
    62  		{
    63  			Id:   model.NewId(),
    64  			Type: jobType,
    65  		},
    66  		{
    67  			Id:   model.NewId(),
    68  			Type: jobType,
    69  		},
    70  		{
    71  			Id:   model.NewId(),
    72  			Type: model.NewId(),
    73  		},
    74  	}
    75  
    76  	for _, job := range jobs {
    77  		store.Must(ss.Job().Save(job))
    78  		defer ss.Job().Delete(job.Id)
    79  	}
    80  
    81  	if result := <-ss.Job().GetAllByType(jobType); result.Err != nil {
    82  		t.Fatal(result.Err)
    83  	} else if received := result.Data.([]*model.Job); len(received) != 2 {
    84  		t.Fatal("received wrong number of jobs")
    85  	} else if received[0].Id != jobs[0].Id && received[1].Id != jobs[0].Id {
    86  		t.Fatal("should've received first jobs")
    87  	} else if received[0].Id != jobs[1].Id && received[1].Id != jobs[1].Id {
    88  		t.Fatal("should've received second jobs")
    89  	}
    90  }
    91  
    92  func testJobGetAllByTypePage(t *testing.T, ss store.Store) {
    93  	jobType := model.NewId()
    94  
    95  	jobs := []*model.Job{
    96  		{
    97  			Id:       model.NewId(),
    98  			Type:     jobType,
    99  			CreateAt: 1000,
   100  		},
   101  		{
   102  			Id:       model.NewId(),
   103  			Type:     jobType,
   104  			CreateAt: 999,
   105  		},
   106  		{
   107  			Id:       model.NewId(),
   108  			Type:     jobType,
   109  			CreateAt: 1001,
   110  		},
   111  		{
   112  			Id:       model.NewId(),
   113  			Type:     model.NewId(),
   114  			CreateAt: 1002,
   115  		},
   116  	}
   117  
   118  	for _, job := range jobs {
   119  		store.Must(ss.Job().Save(job))
   120  		defer ss.Job().Delete(job.Id)
   121  	}
   122  
   123  	if result := <-ss.Job().GetAllByTypePage(jobType, 0, 2); result.Err != nil {
   124  		t.Fatal(result.Err)
   125  	} else if received := result.Data.([]*model.Job); len(received) != 2 {
   126  		t.Fatal("received wrong number of jobs")
   127  	} else if received[0].Id != jobs[2].Id {
   128  		t.Fatal("should've received newest job first")
   129  	} else if received[1].Id != jobs[0].Id {
   130  		t.Fatal("should've received second newest job second")
   131  	}
   132  
   133  	if result := <-ss.Job().GetAllByTypePage(jobType, 2, 2); result.Err != nil {
   134  		t.Fatal(result.Err)
   135  	} else if received := result.Data.([]*model.Job); len(received) != 1 {
   136  		t.Fatal("received wrong number of jobs")
   137  	} else if received[0].Id != jobs[1].Id {
   138  		t.Fatal("should've received oldest job last")
   139  	}
   140  }
   141  
   142  func testJobGetAllPage(t *testing.T, ss store.Store) {
   143  	jobType := model.NewId()
   144  	createAtTime := model.GetMillis()
   145  
   146  	jobs := []*model.Job{
   147  		{
   148  			Id:       model.NewId(),
   149  			Type:     jobType,
   150  			CreateAt: createAtTime + 1,
   151  		},
   152  		{
   153  			Id:       model.NewId(),
   154  			Type:     jobType,
   155  			CreateAt: createAtTime,
   156  		},
   157  		{
   158  			Id:       model.NewId(),
   159  			Type:     jobType,
   160  			CreateAt: createAtTime + 2,
   161  		},
   162  	}
   163  
   164  	for _, job := range jobs {
   165  		store.Must(ss.Job().Save(job))
   166  		defer ss.Job().Delete(job.Id)
   167  	}
   168  
   169  	if result := <-ss.Job().GetAllPage(0, 2); result.Err != nil {
   170  		t.Fatal(result.Err)
   171  	} else if received := result.Data.([]*model.Job); len(received) != 2 {
   172  		t.Fatal("received wrong number of jobs")
   173  	} else if received[0].Id != jobs[2].Id {
   174  		t.Fatal("should've received newest job first")
   175  	} else if received[1].Id != jobs[0].Id {
   176  		t.Fatal("should've received second newest job second")
   177  	}
   178  
   179  	if result := <-ss.Job().GetAllPage(2, 2); result.Err != nil {
   180  		t.Fatal(result.Err)
   181  	} else if received := result.Data.([]*model.Job); len(received) < 1 {
   182  		t.Fatal("received wrong number of jobs")
   183  	} else if received[0].Id != jobs[1].Id {
   184  		t.Fatal("should've received oldest job last")
   185  	}
   186  }
   187  
   188  func testJobGetAllByStatus(t *testing.T, ss store.Store) {
   189  	jobType := model.NewId()
   190  	status := model.NewId()
   191  
   192  	jobs := []*model.Job{
   193  		{
   194  			Id:       model.NewId(),
   195  			Type:     jobType,
   196  			CreateAt: 1000,
   197  			Status:   status,
   198  			Data: map[string]string{
   199  				"test": "data",
   200  			},
   201  		},
   202  		{
   203  			Id:       model.NewId(),
   204  			Type:     jobType,
   205  			CreateAt: 999,
   206  			Status:   status,
   207  		},
   208  		{
   209  			Id:       model.NewId(),
   210  			Type:     jobType,
   211  			CreateAt: 1001,
   212  			Status:   status,
   213  		},
   214  		{
   215  			Id:       model.NewId(),
   216  			Type:     jobType,
   217  			CreateAt: 1002,
   218  			Status:   model.NewId(),
   219  		},
   220  	}
   221  
   222  	for _, job := range jobs {
   223  		store.Must(ss.Job().Save(job))
   224  		defer ss.Job().Delete(job.Id)
   225  	}
   226  
   227  	if result := <-ss.Job().GetAllByStatus(status); result.Err != nil {
   228  		t.Fatal(result.Err)
   229  	} else if received := result.Data.([]*model.Job); len(received) != 3 {
   230  		t.Fatal("received wrong number of jobs")
   231  	} else if received[0].Id != jobs[1].Id || received[1].Id != jobs[0].Id || received[2].Id != jobs[2].Id {
   232  		t.Fatal("should've received jobs ordered by CreateAt time")
   233  	} else if received[1].Data["test"] != "data" {
   234  		t.Fatal("should've received job data field back as saved")
   235  	}
   236  }
   237  
   238  func testJobStoreGetNewestJobByStatusAndType(t *testing.T, ss store.Store) {
   239  	jobType1 := model.NewId()
   240  	jobType2 := model.NewId()
   241  	status1 := model.NewId()
   242  	status2 := model.NewId()
   243  
   244  	jobs := []*model.Job{
   245  		{
   246  			Id:       model.NewId(),
   247  			Type:     jobType1,
   248  			CreateAt: 1001,
   249  			Status:   status1,
   250  		},
   251  		{
   252  			Id:       model.NewId(),
   253  			Type:     jobType1,
   254  			CreateAt: 1000,
   255  			Status:   status1,
   256  		},
   257  		{
   258  			Id:       model.NewId(),
   259  			Type:     jobType2,
   260  			CreateAt: 1003,
   261  			Status:   status1,
   262  		},
   263  		{
   264  			Id:       model.NewId(),
   265  			Type:     jobType1,
   266  			CreateAt: 1004,
   267  			Status:   status2,
   268  		},
   269  	}
   270  
   271  	for _, job := range jobs {
   272  		store.Must(ss.Job().Save(job))
   273  		defer ss.Job().Delete(job.Id)
   274  	}
   275  
   276  	result := <-ss.Job().GetNewestJobByStatusAndType(status1, jobType1)
   277  	assert.Nil(t, result.Err)
   278  	assert.EqualValues(t, jobs[0].Id, result.Data.(*model.Job).Id)
   279  
   280  	result = <-ss.Job().GetNewestJobByStatusAndType(model.NewId(), model.NewId())
   281  	assert.Nil(t, result.Err)
   282  	assert.Nil(t, result.Data.(*model.Job))
   283  }
   284  
   285  func testJobStoreGetCountByStatusAndType(t *testing.T, ss store.Store) {
   286  	jobType1 := model.NewId()
   287  	jobType2 := model.NewId()
   288  	status1 := model.NewId()
   289  	status2 := model.NewId()
   290  
   291  	jobs := []*model.Job{
   292  		{
   293  			Id:       model.NewId(),
   294  			Type:     jobType1,
   295  			CreateAt: 1000,
   296  			Status:   status1,
   297  		},
   298  		{
   299  			Id:       model.NewId(),
   300  			Type:     jobType1,
   301  			CreateAt: 999,
   302  			Status:   status1,
   303  		},
   304  		{
   305  			Id:       model.NewId(),
   306  			Type:     jobType2,
   307  			CreateAt: 1001,
   308  			Status:   status1,
   309  		},
   310  		{
   311  			Id:       model.NewId(),
   312  			Type:     jobType1,
   313  			CreateAt: 1002,
   314  			Status:   status2,
   315  		},
   316  	}
   317  
   318  	for _, job := range jobs {
   319  		store.Must(ss.Job().Save(job))
   320  		defer ss.Job().Delete(job.Id)
   321  	}
   322  
   323  	result := <-ss.Job().GetCountByStatusAndType(status1, jobType1)
   324  	assert.Nil(t, result.Err)
   325  	assert.EqualValues(t, 2, result.Data.(int64))
   326  
   327  	result = <-ss.Job().GetCountByStatusAndType(status2, jobType2)
   328  	assert.Nil(t, result.Err)
   329  	assert.EqualValues(t, 0, result.Data.(int64))
   330  
   331  	result = <-ss.Job().GetCountByStatusAndType(status1, jobType2)
   332  	assert.Nil(t, result.Err)
   333  	assert.EqualValues(t, 1, result.Data.(int64))
   334  
   335  	result = <-ss.Job().GetCountByStatusAndType(status2, jobType1)
   336  	assert.Nil(t, result.Err)
   337  	assert.EqualValues(t, 1, result.Data.(int64))
   338  }
   339  
   340  func testJobUpdateOptimistically(t *testing.T, ss store.Store) {
   341  	job := &model.Job{
   342  		Id:       model.NewId(),
   343  		Type:     model.JOB_TYPE_DATA_RETENTION,
   344  		CreateAt: model.GetMillis(),
   345  		Status:   model.JOB_STATUS_PENDING,
   346  	}
   347  
   348  	if result := <-ss.Job().Save(job); result.Err != nil {
   349  		t.Fatal(result.Err)
   350  	}
   351  	defer ss.Job().Delete(job.Id)
   352  
   353  	job.LastActivityAt = model.GetMillis()
   354  	job.Status = model.JOB_STATUS_IN_PROGRESS
   355  	job.Progress = 50
   356  	job.Data = map[string]string{
   357  		"Foo": "Bar",
   358  	}
   359  
   360  	if result := <-ss.Job().UpdateOptimistically(job, model.JOB_STATUS_SUCCESS); result.Err != nil {
   361  		if result.Data.(bool) {
   362  			t.Fatal("should have failed due to incorrect old status")
   363  		}
   364  	}
   365  
   366  	time.Sleep(2 * time.Millisecond)
   367  
   368  	if result := <-ss.Job().UpdateOptimistically(job, model.JOB_STATUS_PENDING); result.Err != nil {
   369  		t.Fatal(result.Err)
   370  	} else {
   371  		if !result.Data.(bool) {
   372  			t.Fatal("Should have successfully updated")
   373  		}
   374  
   375  		var updatedJob *model.Job
   376  
   377  		if result := <-ss.Job().Get(job.Id); result.Err != nil {
   378  			t.Fatal(result.Err)
   379  		} else {
   380  			updatedJob = result.Data.(*model.Job)
   381  		}
   382  
   383  		if updatedJob.Type != job.Type || updatedJob.CreateAt != job.CreateAt || updatedJob.Status != job.Status || updatedJob.LastActivityAt <= job.LastActivityAt || updatedJob.Progress != job.Progress || updatedJob.Data["Foo"] != job.Data["Foo"] {
   384  			t.Fatal("Some update property was not as expected")
   385  		}
   386  	}
   387  
   388  }
   389  
   390  func testJobUpdateStatusUpdateStatusOptimistically(t *testing.T, ss store.Store) {
   391  	job := &model.Job{
   392  		Id:       model.NewId(),
   393  		Type:     model.JOB_TYPE_DATA_RETENTION,
   394  		CreateAt: model.GetMillis(),
   395  		Status:   model.JOB_STATUS_SUCCESS,
   396  	}
   397  
   398  	var lastUpdateAt int64
   399  	if result := <-ss.Job().Save(job); result.Err != nil {
   400  		t.Fatal(result.Err)
   401  	} else {
   402  		lastUpdateAt = result.Data.(*model.Job).LastActivityAt
   403  	}
   404  
   405  	defer ss.Job().Delete(job.Id)
   406  
   407  	time.Sleep(2 * time.Millisecond)
   408  
   409  	if result := <-ss.Job().UpdateStatus(job.Id, model.JOB_STATUS_PENDING); result.Err != nil {
   410  		t.Fatal(result.Err)
   411  	} else {
   412  		received := result.Data.(*model.Job)
   413  		if received.Status != model.JOB_STATUS_PENDING {
   414  			t.Fatal("status wasn't updated")
   415  		}
   416  		if received.LastActivityAt <= lastUpdateAt {
   417  			t.Fatal("lastActivityAt wasn't updated")
   418  		}
   419  		lastUpdateAt = received.LastActivityAt
   420  	}
   421  
   422  	time.Sleep(2 * time.Millisecond)
   423  
   424  	if result := <-ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_IN_PROGRESS, model.JOB_STATUS_SUCCESS); result.Err != nil {
   425  		t.Fatal(result.Err)
   426  	} else {
   427  		if result.Data.(bool) {
   428  			t.Fatal("should be false due to incorrect original status")
   429  		}
   430  	}
   431  
   432  	if result := <-ss.Job().Get(job.Id); result.Err != nil {
   433  		t.Fatal(result.Err)
   434  	} else {
   435  		received := result.Data.(*model.Job)
   436  		if received.Status != model.JOB_STATUS_PENDING {
   437  			t.Fatal("should still be pending")
   438  		}
   439  		if received.LastActivityAt != lastUpdateAt {
   440  			t.Fatal("last activity at shouldn't have changed")
   441  		}
   442  	}
   443  
   444  	time.Sleep(2 * time.Millisecond)
   445  
   446  	if result := <-ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_PENDING, model.JOB_STATUS_IN_PROGRESS); result.Err != nil {
   447  		t.Fatal(result.Err)
   448  	} else {
   449  		if !result.Data.(bool) {
   450  			t.Fatal("should have succeeded")
   451  		}
   452  	}
   453  
   454  	var startAtSet int64
   455  	if result := <-ss.Job().Get(job.Id); result.Err != nil {
   456  		t.Fatal(result.Err)
   457  	} else {
   458  		received := result.Data.(*model.Job)
   459  		if received.Status != model.JOB_STATUS_IN_PROGRESS {
   460  			t.Fatal("should be in progress")
   461  		}
   462  		if received.StartAt == 0 {
   463  			t.Fatal("received should have start at set")
   464  		}
   465  		if received.LastActivityAt <= lastUpdateAt {
   466  			t.Fatal("lastActivityAt wasn't updated")
   467  		}
   468  		lastUpdateAt = received.LastActivityAt
   469  		startAtSet = received.StartAt
   470  	}
   471  
   472  	time.Sleep(2 * time.Millisecond)
   473  
   474  	if result := <-ss.Job().UpdateStatusOptimistically(job.Id, model.JOB_STATUS_IN_PROGRESS, model.JOB_STATUS_SUCCESS); result.Err != nil {
   475  		t.Fatal(result.Err)
   476  	} else {
   477  		if !result.Data.(bool) {
   478  			t.Fatal("should have succeeded")
   479  		}
   480  	}
   481  
   482  	if result := <-ss.Job().Get(job.Id); result.Err != nil {
   483  		t.Fatal(result.Err)
   484  	} else {
   485  		received := result.Data.(*model.Job)
   486  		if received.Status != model.JOB_STATUS_SUCCESS {
   487  			t.Fatal("should be success status")
   488  		}
   489  		if received.StartAt != startAtSet {
   490  			t.Fatal("startAt should not have changed")
   491  		}
   492  		if received.LastActivityAt <= lastUpdateAt {
   493  			t.Fatal("lastActivityAt wasn't updated")
   494  		}
   495  	}
   496  }
   497  
   498  func testJobDelete(t *testing.T, ss store.Store) {
   499  	job := store.Must(ss.Job().Save(&model.Job{
   500  		Id: model.NewId(),
   501  	})).(*model.Job)
   502  
   503  	if result := <-ss.Job().Delete(job.Id); result.Err != nil {
   504  		t.Fatal(result.Err)
   505  	}
   506  }