github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/migrations/scheduler.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package migrations 5 6 import ( 7 "time" 8 9 "github.com/masterhung0112/hk_server/v5/app" 10 "github.com/masterhung0112/hk_server/v5/model" 11 "github.com/masterhung0112/hk_server/v5/shared/mlog" 12 ) 13 14 const ( 15 MigrationJobWedgedTimeoutMilliseconds = 3600000 // 1 hour 16 ) 17 18 type Scheduler struct { 19 srv *app.Server 20 allMigrationsCompleted bool 21 } 22 23 func (m *MigrationsJobInterfaceImpl) MakeScheduler() model.Scheduler { 24 return &Scheduler{m.srv, false} 25 } 26 27 func (scheduler *Scheduler) Name() string { 28 return "MigrationsScheduler" 29 } 30 31 func (scheduler *Scheduler) JobType() string { 32 return model.JOB_TYPE_MIGRATIONS 33 } 34 35 func (scheduler *Scheduler) Enabled(_ *model.Config) bool { 36 return true 37 } 38 39 //nolint:unparam 40 func (scheduler *Scheduler) NextScheduleTime(cfg *model.Config, now time.Time, pendingJobs bool, lastSuccessfulJob *model.Job) *time.Time { 41 if scheduler.allMigrationsCompleted { 42 return nil 43 } 44 45 nextTime := time.Now().Add(60 * time.Second) 46 return &nextTime 47 } 48 49 //nolint:unparam 50 func (scheduler *Scheduler) ScheduleJob(cfg *model.Config, pendingJobs bool, lastSuccessfulJob *model.Job) (*model.Job, *model.AppError) { 51 mlog.Debug("Scheduling Job", mlog.String("scheduler", scheduler.Name())) 52 53 // Work through the list of migrations in order. Schedule the first one that isn't done (assuming it isn't in progress already). 54 for _, key := range MakeMigrationsList() { 55 state, job, err := GetMigrationState(key, scheduler.srv.Store) 56 if err != nil { 57 mlog.Error("Failed to determine status of migration: ", mlog.String("scheduler", scheduler.Name()), mlog.String("migration_key", key), mlog.String("error", err.Error())) 58 return nil, nil 59 } 60 61 if state == MigrationStateInProgress { 62 // Check the migration job isn't wedged. 63 if job != nil && job.LastActivityAt < model.GetMillis()-MigrationJobWedgedTimeoutMilliseconds && job.CreateAt < model.GetMillis()-MigrationJobWedgedTimeoutMilliseconds { 64 mlog.Warn("Job appears to be wedged. Rescheduling another instance.", mlog.String("scheduler", scheduler.Name()), mlog.String("wedged_job_id", job.Id), mlog.String("migration_key", key)) 65 if err := scheduler.srv.Jobs.SetJobError(job, nil); err != nil { 66 mlog.Error("Worker: Failed to set job error", mlog.String("scheduler", scheduler.Name()), mlog.String("job_id", job.Id), mlog.String("error", err.Error())) 67 } 68 return scheduler.createJob(key, job) 69 } 70 71 return nil, nil 72 } 73 74 if state == MigrationStateCompleted { 75 // This migration is done. Continue to check the next. 76 continue 77 } 78 79 if state == MigrationStateUnscheduled { 80 mlog.Debug("Scheduling a new job for migration.", mlog.String("scheduler", scheduler.Name()), mlog.String("migration_key", key)) 81 return scheduler.createJob(key, job) 82 } 83 84 mlog.Error("Unknown migration state. Not doing anything.", mlog.String("migration_state", state)) 85 return nil, nil 86 } 87 88 // If we reached here, then there aren't any migrations left to run. 89 scheduler.allMigrationsCompleted = true 90 mlog.Debug("All migrations are complete.", mlog.String("scheduler", scheduler.Name())) 91 92 return nil, nil 93 } 94 95 func (scheduler *Scheduler) createJob(migrationKey string, lastJob *model.Job) (*model.Job, *model.AppError) { 96 var lastDone string 97 if lastJob != nil { 98 lastDone = lastJob.Data[JobDataKeyMigration_LAST_DONE] 99 } 100 101 data := map[string]string{ 102 JobDataKeyMigration: migrationKey, 103 JobDataKeyMigration_LAST_DONE: lastDone, 104 } 105 106 job, err := scheduler.srv.Jobs.CreateJob(model.JOB_TYPE_MIGRATIONS, data) 107 if err != nil { 108 return nil, err 109 } 110 return job, nil 111 }