MM-27449: Compliance Jobs rerun after warning status (#15178)
* add warning as success result * revert config changes * add unit test, update unit test * add a couple more tests * update store layers Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
d48eec6727
Коммит
0302e0f477
@@ -169,9 +169,13 @@ func buildExportCmdF(format string) func(command *cobra.Command, args []string)
|
|||||||
}
|
}
|
||||||
if warningsCount == 0 {
|
if warningsCount == 0 {
|
||||||
CommandPrettyPrintln("SUCCESS: Your data was exported.")
|
CommandPrettyPrintln("SUCCESS: Your data was exported.")
|
||||||
|
} else {
|
||||||
|
if format == model.COMPLIANCE_EXPORT_TYPE_GLOBALRELAY || format == model.COMPLIANCE_EXPORT_TYPE_GLOBALRELAY_ZIP {
|
||||||
|
CommandPrettyPrintln(fmt.Sprintf("WARNING: %d warnings encountered, see logs for details.", warningsCount))
|
||||||
} else {
|
} else {
|
||||||
CommandPrettyPrintln(fmt.Sprintf("WARNING: %d warnings encountered, see warning.txt for details.", warningsCount))
|
CommandPrettyPrintln(fmt.Sprintf("WARNING: %d warnings encountered, see warning.txt for details.", warningsCount))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auditRec := a.MakeAuditRecord("buildExport", audit.Success)
|
auditRec := a.MakeAuditRecord("buildExport", audit.Success)
|
||||||
auditRec.AddMeta("format", format)
|
auditRec.AddMeta("format", format)
|
||||||
|
|||||||
@@ -174,5 +174,9 @@ func (srv *JobServer) CheckForPendingJobsByType(jobType string) (bool, *model.Ap
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (srv *JobServer) GetLastSuccessfulJobByType(jobType string) (*model.Job, *model.AppError) {
|
func (srv *JobServer) GetLastSuccessfulJobByType(jobType string) (*model.Job, *model.AppError) {
|
||||||
return srv.Store.Job().GetNewestJobByStatusAndType(model.JOB_STATUS_SUCCESS, jobType)
|
statuses := []string{model.JOB_STATUS_SUCCESS}
|
||||||
|
if jobType == model.JOB_TYPE_MESSAGE_EXPORT {
|
||||||
|
statuses = []string{model.JOB_STATUS_WARNING, model.JOB_STATUS_SUCCESS}
|
||||||
|
}
|
||||||
|
return srv.Store.Job().GetNewestJobByStatusesAndType(statuses, jobType)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func TestScheduler(t *testing.T) {
|
|||||||
Type: model.JOB_TYPE_MESSAGE_EXPORT,
|
Type: model.JOB_TYPE_MESSAGE_EXPORT,
|
||||||
}
|
}
|
||||||
// mock job store doesn't return a previously successful job, forcing fallback to config
|
// mock job store doesn't return a previously successful job, forcing fallback to config
|
||||||
mockStore.JobStore.On("GetNewestJobByStatusAndType", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(job, nil)
|
mockStore.JobStore.On("GetNewestJobByStatusesAndType", mock.AnythingOfType("[]string"), mock.AnythingOfType("string")).Return(job, nil)
|
||||||
mockStore.JobStore.On("GetCountByStatusAndType", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(int64(1), nil)
|
mockStore.JobStore.On("GetCountByStatusAndType", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(int64(1), nil)
|
||||||
|
|
||||||
jobServer := &JobServer{
|
jobServer := &JobServer{
|
||||||
|
|||||||
@@ -4027,6 +4027,24 @@ func (s *OpenTracingLayerJobStore) GetNewestJobByStatusAndType(status string, jo
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *OpenTracingLayerJobStore) GetNewestJobByStatusesAndType(statuses []string, jobType string) (*model.Job, *model.AppError) {
|
||||||
|
origCtx := s.Root.Store.Context()
|
||||||
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "JobStore.GetNewestJobByStatusesAndType")
|
||||||
|
s.Root.Store.SetContext(newCtx)
|
||||||
|
defer func() {
|
||||||
|
s.Root.Store.SetContext(origCtx)
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer span.Finish()
|
||||||
|
result, err := s.JobStore.GetNewestJobByStatusesAndType(statuses, jobType)
|
||||||
|
if err != nil {
|
||||||
|
span.LogFields(spanlog.Error(err))
|
||||||
|
ext.Error.Set(span, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *OpenTracingLayerJobStore) Save(job *model.Job) (*model.Job, *model.AppError) {
|
func (s *OpenTracingLayerJobStore) Save(job *model.Job) (*model.Job, *model.AppError) {
|
||||||
origCtx := s.Root.Store.Context()
|
origCtx := s.Root.Store.Context()
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "JobStore.Save")
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "JobStore.Save")
|
||||||
|
|||||||
@@ -2540,6 +2540,12 @@ func (s *RetryLayerJobStore) GetNewestJobByStatusAndType(status string, jobType
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *RetryLayerJobStore) GetNewestJobByStatusesAndType(statuses []string, jobType string) (*model.Job, *model.AppError) {
|
||||||
|
|
||||||
|
return s.JobStore.GetNewestJobByStatusesAndType(statuses, jobType)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (s *RetryLayerJobStore) Save(job *model.Job) (*model.Job, *model.AppError) {
|
func (s *RetryLayerJobStore) Save(job *model.Job) (*model.Job, *model.AppError) {
|
||||||
|
|
||||||
return s.JobStore.Save(job)
|
return s.JobStore.Save(job)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package sqlstore
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
|
||||||
@@ -205,8 +206,11 @@ func (jss SqlJobStore) GetAllByStatus(status string) ([]*model.Job, *model.AppEr
|
|||||||
}
|
}
|
||||||
return statuses, nil
|
return statuses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jss SqlJobStore) GetNewestJobByStatusAndType(status string, jobType string) (*model.Job, *model.AppError) {
|
func (jss SqlJobStore) GetNewestJobByStatusAndType(status string, jobType string) (*model.Job, *model.AppError) {
|
||||||
|
return jss.GetNewestJobByStatusesAndType([]string{status}, jobType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (jss SqlJobStore) GetNewestJobByStatusesAndType(status []string, jobType string) (*model.Job, *model.AppError) {
|
||||||
query, args, err := jss.getQueryBuilder().
|
query, args, err := jss.getQueryBuilder().
|
||||||
Select("*").
|
Select("*").
|
||||||
From("Jobs").
|
From("Jobs").
|
||||||
@@ -219,7 +223,7 @@ func (jss SqlJobStore) GetNewestJobByStatusAndType(status string, jobType string
|
|||||||
|
|
||||||
var job *model.Job
|
var job *model.Job
|
||||||
if err = jss.GetReplica().SelectOne(&job, query, args...); err != nil && err != sql.ErrNoRows {
|
if err = jss.GetReplica().SelectOne(&job, query, args...); err != nil && err != sql.ErrNoRows {
|
||||||
return nil, model.NewAppError("SqlJobStore.GetNewestJobByStatusAndType", "store.sql_job.get_newest_job_by_status_and_type.app_error", nil, "Status="+status+", "+err.Error(), http.StatusInternalServerError)
|
return nil, model.NewAppError("SqlJobStore.GetNewestJobByStatusAndType", "store.sql_job.get_newest_job_by_status_and_type.app_error", nil, "Status="+strings.Join(status, ",")+", "+err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
return job, nil
|
return job, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -569,6 +569,7 @@ type JobStore interface {
|
|||||||
GetAllByTypePage(jobType string, offset int, limit int) ([]*model.Job, *model.AppError)
|
GetAllByTypePage(jobType string, offset int, limit int) ([]*model.Job, *model.AppError)
|
||||||
GetAllByStatus(status string) ([]*model.Job, *model.AppError)
|
GetAllByStatus(status string) ([]*model.Job, *model.AppError)
|
||||||
GetNewestJobByStatusAndType(status string, jobType string) (*model.Job, *model.AppError)
|
GetNewestJobByStatusAndType(status string, jobType string) (*model.Job, *model.AppError)
|
||||||
|
GetNewestJobByStatusesAndType(statuses []string, jobType string) (*model.Job, *model.AppError)
|
||||||
GetCountByStatusAndType(status string, jobType string) (int64, *model.AppError)
|
GetCountByStatusAndType(status string, jobType string) (int64, *model.AppError)
|
||||||
Delete(id string) (string, *model.AppError)
|
Delete(id string) (string, *model.AppError)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ func TestJobStore(t *testing.T, ss store.Store) {
|
|||||||
t.Run("JobGetAllPage", func(t *testing.T) { testJobGetAllPage(t, ss) })
|
t.Run("JobGetAllPage", func(t *testing.T) { testJobGetAllPage(t, ss) })
|
||||||
t.Run("JobGetAllByStatus", func(t *testing.T) { testJobGetAllByStatus(t, ss) })
|
t.Run("JobGetAllByStatus", func(t *testing.T) { testJobGetAllByStatus(t, ss) })
|
||||||
t.Run("GetNewestJobByStatusAndType", func(t *testing.T) { testJobStoreGetNewestJobByStatusAndType(t, ss) })
|
t.Run("GetNewestJobByStatusAndType", func(t *testing.T) { testJobStoreGetNewestJobByStatusAndType(t, ss) })
|
||||||
|
t.Run("GetNewestJobByStatusesAndType", func(t *testing.T) { testJobStoreGetNewestJobByStatusesAndType(t, ss) })
|
||||||
t.Run("GetCountByStatusAndType", func(t *testing.T) { testJobStoreGetCountByStatusAndType(t, ss) })
|
t.Run("GetCountByStatusAndType", func(t *testing.T) { testJobStoreGetCountByStatusAndType(t, ss) })
|
||||||
t.Run("JobUpdateOptimistically", func(t *testing.T) { testJobUpdateOptimistically(t, ss) })
|
t.Run("JobUpdateOptimistically", func(t *testing.T) { testJobUpdateOptimistically(t, ss) })
|
||||||
t.Run("JobUpdateStatusUpdateStatusOptimistically", func(t *testing.T) { testJobUpdateStatusUpdateStatusOptimistically(t, ss) })
|
t.Run("JobUpdateStatusUpdateStatusOptimistically", func(t *testing.T) { testJobUpdateStatusUpdateStatusOptimistically(t, ss) })
|
||||||
@@ -261,6 +262,66 @@ func testJobStoreGetNewestJobByStatusAndType(t *testing.T, ss store.Store) {
|
|||||||
assert.Nil(t, received)
|
assert.Nil(t, received)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testJobStoreGetNewestJobByStatusesAndType(t *testing.T, ss store.Store) {
|
||||||
|
jobType1 := model.NewId()
|
||||||
|
jobType2 := model.NewId()
|
||||||
|
status1 := model.NewId()
|
||||||
|
status2 := model.NewId()
|
||||||
|
|
||||||
|
jobs := []*model.Job{
|
||||||
|
{
|
||||||
|
Id: model.NewId(),
|
||||||
|
Type: jobType1,
|
||||||
|
CreateAt: 1001,
|
||||||
|
Status: status1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: model.NewId(),
|
||||||
|
Type: jobType1,
|
||||||
|
CreateAt: 1000,
|
||||||
|
Status: status1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: model.NewId(),
|
||||||
|
Type: jobType2,
|
||||||
|
CreateAt: 1003,
|
||||||
|
Status: status1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: model.NewId(),
|
||||||
|
Type: jobType1,
|
||||||
|
CreateAt: 1004,
|
||||||
|
Status: status2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, job := range jobs {
|
||||||
|
_, err := ss.Job().Save(job)
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer ss.Job().Delete(job.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
received, err := ss.Job().GetNewestJobByStatusesAndType([]string{status1, status2}, jobType1)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.EqualValues(t, jobs[3].Id, received.Id)
|
||||||
|
|
||||||
|
received, err = ss.Job().GetNewestJobByStatusesAndType([]string{model.NewId(), model.NewId()}, model.NewId())
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Nil(t, received)
|
||||||
|
|
||||||
|
received, err = ss.Job().GetNewestJobByStatusesAndType([]string{status2}, jobType2)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Nil(t, received)
|
||||||
|
|
||||||
|
received, err = ss.Job().GetNewestJobByStatusesAndType([]string{status1}, jobType2)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.EqualValues(t, jobs[2].Id, received.Id)
|
||||||
|
|
||||||
|
received, err = ss.Job().GetNewestJobByStatusesAndType([]string{}, jobType1)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Nil(t, received)
|
||||||
|
}
|
||||||
|
|
||||||
func testJobStoreGetCountByStatusAndType(t *testing.T, ss store.Store) {
|
func testJobStoreGetCountByStatusAndType(t *testing.T, ss store.Store) {
|
||||||
jobType1 := model.NewId()
|
jobType1 := model.NewId()
|
||||||
jobType2 := model.NewId()
|
jobType2 := model.NewId()
|
||||||
|
|||||||
@@ -210,6 +210,31 @@ func (_m *JobStore) GetNewestJobByStatusAndType(status string, jobType string) (
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNewestJobByStatusesAndType provides a mock function with given fields: statuses, jobType
|
||||||
|
func (_m *JobStore) GetNewestJobByStatusesAndType(statuses []string, jobType string) (*model.Job, *model.AppError) {
|
||||||
|
ret := _m.Called(statuses, jobType)
|
||||||
|
|
||||||
|
var r0 *model.Job
|
||||||
|
if rf, ok := ret.Get(0).(func([]string, string) *model.Job); ok {
|
||||||
|
r0 = rf(statuses, jobType)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.Job)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 *model.AppError
|
||||||
|
if rf, ok := ret.Get(1).(func([]string, string) *model.AppError); ok {
|
||||||
|
r1 = rf(statuses, jobType)
|
||||||
|
} else {
|
||||||
|
if ret.Get(1) != nil {
|
||||||
|
r1 = ret.Get(1).(*model.AppError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// Save provides a mock function with given fields: job
|
// Save provides a mock function with given fields: job
|
||||||
func (_m *JobStore) Save(job *model.Job) (*model.Job, *model.AppError) {
|
func (_m *JobStore) Save(job *model.Job) (*model.Job, *model.AppError) {
|
||||||
ret := _m.Called(job)
|
ret := _m.Called(job)
|
||||||
|
|||||||
@@ -3663,6 +3663,22 @@ func (s *TimerLayerJobStore) GetNewestJobByStatusAndType(status string, jobType
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TimerLayerJobStore) GetNewestJobByStatusesAndType(statuses []string, jobType string) (*model.Job, *model.AppError) {
|
||||||
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
result, err := s.JobStore.GetNewestJobByStatusesAndType(statuses, jobType)
|
||||||
|
|
||||||
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
|
if s.Root.Metrics != nil {
|
||||||
|
success := "false"
|
||||||
|
if err == nil {
|
||||||
|
success = "true"
|
||||||
|
}
|
||||||
|
s.Root.Metrics.ObserveStoreMethodDuration("JobStore.GetNewestJobByStatusesAndType", success, elapsed)
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TimerLayerJobStore) Save(job *model.Job) (*model.Job, *model.AppError) {
|
func (s *TimerLayerJobStore) Save(job *model.Job) (*model.Job, *model.AppError) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user