[MM-63314] Fix ClaimJob in HA environments (#30383)
* ClaimJob now returns newly claimed job * internal code affected by change * test changes required * two branches: for mysql, use transaction; for postgres, use returning * two branches: for mysql, use transaction; for postgres, use returning * use same millis value for LastActivityAt and StartAt * blank commit --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c9504925e6
Коммит
c049748b88
@@ -71,12 +71,16 @@ func TestClaimJob(t *testing.T) {
|
||||
Id: "job_id",
|
||||
Type: "job_type",
|
||||
}
|
||||
retJob := *job
|
||||
retJob.Status = model.JobStatusInProgress
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusInProgress).Return(false, &model.AppError{Message: "message"})
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusInProgress).
|
||||
Return(&retJob, &model.AppError{Message: "message"})
|
||||
|
||||
updated, err := jobServer.ClaimJob(job)
|
||||
expectErrorId(t, "app.job.update.app_error", err)
|
||||
require.False(t, updated)
|
||||
newJob, appErr := jobServer.ClaimJob(job)
|
||||
expectErrorId(t, "app.job.update.app_error", appErr)
|
||||
require.Nil(t, newJob)
|
||||
})
|
||||
|
||||
t.Run("no existing job to update", func(t *testing.T) {
|
||||
@@ -87,11 +91,13 @@ func TestClaimJob(t *testing.T) {
|
||||
Type: "job_type",
|
||||
}
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusInProgress).Return(false, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusInProgress).
|
||||
Return(nil, nil)
|
||||
|
||||
updated, err := jobServer.ClaimJob(job)
|
||||
require.Nil(t, err)
|
||||
require.False(t, updated)
|
||||
newJob, appErr := jobServer.ClaimJob(job)
|
||||
require.Nil(t, appErr)
|
||||
require.Nil(t, newJob)
|
||||
})
|
||||
|
||||
t.Run("pending job updated", func(t *testing.T) {
|
||||
@@ -101,13 +107,17 @@ func TestClaimJob(t *testing.T) {
|
||||
Id: "job_id",
|
||||
Type: "job_type",
|
||||
}
|
||||
retJob := *job
|
||||
retJob.Status = model.JobStatusInProgress
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusInProgress).Return(true, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusInProgress).
|
||||
Return(&retJob, nil)
|
||||
mockMetrics.On("IncrementJobActive", "job_type")
|
||||
|
||||
updated, err := jobServer.ClaimJob(job)
|
||||
newJob, err := jobServer.ClaimJob(job)
|
||||
require.Nil(t, err)
|
||||
require.True(t, updated)
|
||||
require.NotNil(t, newJob)
|
||||
})
|
||||
|
||||
t.Run("pending job updated, nil metrics service", func(t *testing.T) {
|
||||
@@ -117,12 +127,16 @@ func TestClaimJob(t *testing.T) {
|
||||
Id: "job_id",
|
||||
Type: "job_type",
|
||||
}
|
||||
retJob := *job
|
||||
retJob.Status = model.JobStatusInProgress
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusInProgress).Return(true, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusInProgress).
|
||||
Return(&retJob, nil)
|
||||
|
||||
updated, err := jobServer.ClaimJob(job)
|
||||
require.Nil(t, err)
|
||||
require.True(t, updated)
|
||||
newJob, appErr := jobServer.ClaimJob(job)
|
||||
require.Nil(t, appErr)
|
||||
require.NotNil(t, newJob)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -136,10 +150,9 @@ func TestSetJobProgress(t *testing.T) {
|
||||
Type: "job_type",
|
||||
}
|
||||
|
||||
job.Status = model.JobStatusInProgress
|
||||
job.Progress = progress
|
||||
|
||||
mockStore.JobStore.On("UpdateOptimistically", job, model.JobStatusInProgress).Return(false, &model.AppError{Message: "message"})
|
||||
mockStore.JobStore.
|
||||
On("UpdateOptimistically", job, model.JobStatusInProgress).
|
||||
Return(false, &model.AppError{Message: "message"})
|
||||
|
||||
err := jobServer.SetJobProgress(job, progress)
|
||||
expectErrorId(t, "app.job.update.app_error", err)
|
||||
@@ -157,7 +170,9 @@ func TestSetJobProgress(t *testing.T) {
|
||||
job.Status = model.JobStatusInProgress
|
||||
job.Progress = progress
|
||||
|
||||
mockStore.JobStore.On("UpdateOptimistically", job, model.JobStatusInProgress).Return(true, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateOptimistically", job, model.JobStatusInProgress).
|
||||
Return(true, nil)
|
||||
|
||||
err := jobServer.SetJobProgress(job, progress)
|
||||
require.Nil(t, err)
|
||||
@@ -173,7 +188,9 @@ func TestSetJobWarning(t *testing.T) {
|
||||
Type: "job_type",
|
||||
}
|
||||
|
||||
mockStore.JobStore.On("UpdateStatus", "job_id", model.JobStatusWarning).Return(job, &model.AppError{Message: "message"})
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatus", "job_id", model.JobStatusWarning).
|
||||
Return(nil, &model.AppError{Message: "message"})
|
||||
|
||||
err := jobServer.SetJobWarning(job)
|
||||
expectErrorId(t, "app.job.update.app_error", err)
|
||||
@@ -186,8 +203,12 @@ func TestSetJobWarning(t *testing.T) {
|
||||
Id: "job_id",
|
||||
Type: "job_type",
|
||||
}
|
||||
retJob := *job
|
||||
retJob.Status = model.JobStatusWarning
|
||||
|
||||
mockStore.JobStore.On("UpdateStatus", "job_id", model.JobStatusWarning).Return(job, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatus", "job_id", model.JobStatusWarning).
|
||||
Return(&retJob, nil)
|
||||
|
||||
err := jobServer.SetJobWarning(job)
|
||||
require.Nil(t, err)
|
||||
@@ -249,7 +270,9 @@ func TestSetJobError(t *testing.T) {
|
||||
Type: "job_type",
|
||||
}
|
||||
|
||||
mockStore.JobStore.On("UpdateStatus", "job_id", model.JobStatusError).Return(job, &model.AppError{Message: "message"})
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatus", "job_id", model.JobStatusError).
|
||||
Return(nil, &model.AppError{Message: "message"})
|
||||
|
||||
err := jobServer.SetJobError(job, nil)
|
||||
expectErrorId(t, "app.job.update.app_error", err)
|
||||
@@ -263,7 +286,9 @@ func TestSetJobError(t *testing.T) {
|
||||
Type: "job_type",
|
||||
}
|
||||
|
||||
mockStore.JobStore.On("UpdateStatus", "job_id", model.JobStatusError).Return(job, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatus", "job_id", model.JobStatusError).
|
||||
Return(job, nil)
|
||||
mockMetrics.On("DecrementJobActive", "job_type")
|
||||
|
||||
err := jobServer.SetJobError(job, nil)
|
||||
@@ -298,7 +323,9 @@ func TestSetJobError(t *testing.T) {
|
||||
Data: map[string]string{"error": jobError.Message},
|
||||
}
|
||||
|
||||
mockStore.JobStore.On("UpdateOptimistically", job, model.JobStatusInProgress).Return(false, &model.AppError{Message: "message"})
|
||||
mockStore.JobStore.
|
||||
On("UpdateOptimistically", job, model.JobStatusInProgress).
|
||||
Return(false, &model.AppError{Message: "message"})
|
||||
|
||||
err := jobServer.SetJobError(job, jobError)
|
||||
expectErrorId(t, "app.job.update.app_error", err)
|
||||
@@ -566,7 +593,9 @@ func TestRequestCancellation(t *testing.T) {
|
||||
t.Run("error cancelling", func(t *testing.T) {
|
||||
jobServer, mockStore, _ := makeJobServer(t)
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).Return(false, &model.AppError{Message: "message"})
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).
|
||||
Return(nil, &model.AppError{Message: "message"})
|
||||
|
||||
err := jobServer.RequestCancellation(ctx, "job_id")
|
||||
expectErrorId(t, "app.job.update.app_error", err)
|
||||
@@ -575,8 +604,17 @@ func TestRequestCancellation(t *testing.T) {
|
||||
t.Run("cancelled, job not found", func(t *testing.T) {
|
||||
jobServer, mockStore, _ := makeJobServer(t)
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).Return(true, nil)
|
||||
mockStore.JobStore.On("Get", mock.AnythingOfType("*request.Context"), "job_id").Return(nil, &store.ErrNotFound{})
|
||||
job := &model.Job{
|
||||
Id: "job_id",
|
||||
Type: "job_type",
|
||||
}
|
||||
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).
|
||||
Return(job, nil)
|
||||
mockStore.JobStore.
|
||||
On("Get", mock.AnythingOfType("*request.Context"), "job_id").
|
||||
Return(nil, &store.ErrNotFound{})
|
||||
|
||||
err := jobServer.RequestCancellation(ctx, "job_id")
|
||||
expectErrorId(t, "app.job.update.app_error", err)
|
||||
@@ -590,8 +628,12 @@ func TestRequestCancellation(t *testing.T) {
|
||||
Type: "job_type",
|
||||
}
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).Return(true, nil)
|
||||
mockStore.JobStore.On("Get", mock.AnythingOfType("*request.Context"), "job_id").Return(job, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).
|
||||
Return(job, nil)
|
||||
mockStore.JobStore.
|
||||
On("Get", mock.AnythingOfType("*request.Context"), "job_id").
|
||||
Return(job, nil)
|
||||
mockMetrics.On("DecrementJobActive", "job_type")
|
||||
|
||||
err := jobServer.RequestCancellation(ctx, "job_id")
|
||||
@@ -601,7 +643,14 @@ func TestRequestCancellation(t *testing.T) {
|
||||
t.Run("cancelled, success, nil metrics service", func(t *testing.T) {
|
||||
jobServer, mockStore := makeTeamEditionJobServer(t)
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).Return(true, nil)
|
||||
job := &model.Job{
|
||||
Id: "job_id",
|
||||
Type: "job_type",
|
||||
}
|
||||
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).
|
||||
Return(job, nil)
|
||||
|
||||
err := jobServer.RequestCancellation(ctx, "job_id")
|
||||
require.Nil(t, err)
|
||||
@@ -610,8 +659,12 @@ func TestRequestCancellation(t *testing.T) {
|
||||
t.Run("unable to cancel, requesting cancellation instead, error setting status", func(t *testing.T) {
|
||||
jobServer, mockStore, _ := makeJobServer(t)
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).Return(false, nil)
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusInProgress, model.JobStatusCancelRequested).Return(false, &model.AppError{Message: "message"})
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).
|
||||
Return(nil, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusInProgress, model.JobStatusCancelRequested).
|
||||
Return(nil, &model.AppError{Message: "message"})
|
||||
|
||||
err := jobServer.RequestCancellation(ctx, "job_id")
|
||||
expectErrorId(t, "app.job.update.app_error", err)
|
||||
@@ -620,8 +673,17 @@ func TestRequestCancellation(t *testing.T) {
|
||||
t.Run("unable to cancel, requesting cancellation instead, success", func(t *testing.T) {
|
||||
jobServer, mockStore, _ := makeJobServer(t)
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).Return(false, nil)
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusInProgress, model.JobStatusCancelRequested).Return(true, nil)
|
||||
job := &model.Job{
|
||||
Id: "job_id",
|
||||
Type: "job_type",
|
||||
}
|
||||
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).
|
||||
Return(nil, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusInProgress, model.JobStatusCancelRequested).
|
||||
Return(job, nil)
|
||||
|
||||
err := jobServer.RequestCancellation(ctx, "job_id")
|
||||
require.Nil(t, err)
|
||||
@@ -630,8 +692,12 @@ func TestRequestCancellation(t *testing.T) {
|
||||
t.Run("unable to cancel, requesting cancellation instead, unexpected state", func(t *testing.T) {
|
||||
jobServer, mockStore, _ := makeJobServer(t)
|
||||
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).Return(false, nil)
|
||||
mockStore.JobStore.On("UpdateStatusOptimistically", "job_id", model.JobStatusInProgress, model.JobStatusCancelRequested).Return(false, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusPending, model.JobStatusCanceled).
|
||||
Return(nil, nil)
|
||||
mockStore.JobStore.
|
||||
On("UpdateStatusOptimistically", "job_id", model.JobStatusInProgress, model.JobStatusCancelRequested).
|
||||
Return(nil, nil)
|
||||
|
||||
err := jobServer.RequestCancellation(ctx, "job_id")
|
||||
expectErrorId(t, "jobs.request_cancellation.status.error", err)
|
||||
|
||||
Ссылка в новой задаче
Block a user