github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/store/sqlstore/job_store.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package sqlstore 5 6 import ( 7 "database/sql" 8 "fmt" 9 "strings" 10 11 sq "github.com/Masterminds/squirrel" 12 "github.com/mattermost/gorp" 13 "github.com/pkg/errors" 14 15 "github.com/masterhung0112/hk_server/v5/model" 16 "github.com/masterhung0112/hk_server/v5/store" 17 ) 18 19 type SqlJobStore struct { 20 *SqlStore 21 } 22 23 func newSqlJobStore(sqlStore *SqlStore) store.JobStore { 24 s := &SqlJobStore{sqlStore} 25 26 for _, db := range sqlStore.GetAllConns() { 27 table := db.AddTableWithName(model.Job{}, "Jobs").SetKeys(false, "Id") 28 table.ColMap("Id").SetMaxSize(26) 29 table.ColMap("Type").SetMaxSize(32) 30 table.ColMap("Status").SetMaxSize(32) 31 table.ColMap("Data").SetMaxSize(1024) 32 } 33 34 return s 35 } 36 37 func (jss SqlJobStore) createIndexesIfNotExists() { 38 jss.CreateIndexIfNotExists("idx_jobs_type", "Jobs", "Type") 39 } 40 41 func (jss SqlJobStore) Save(job *model.Job) (*model.Job, error) { 42 if err := jss.GetMaster().Insert(job); err != nil { 43 return nil, errors.Wrap(err, "failed to save Job") 44 } 45 return job, nil 46 } 47 48 func (jss SqlJobStore) UpdateOptimistically(job *model.Job, currentStatus string) (bool, error) { 49 query, args, err := jss.getQueryBuilder(). 50 Update("Jobs"). 51 Set("LastActivityAt", model.GetMillis()). 52 Set("Status", job.Status). 53 Set("Data", job.DataToJson()). 54 Set("Progress", job.Progress). 55 Where(sq.Eq{"Id": job.Id, "Status": currentStatus}).ToSql() 56 if err != nil { 57 return false, errors.Wrap(err, "job_tosql") 58 } 59 sqlResult, err := jss.GetMaster().Exec(query, args...) 60 if err != nil { 61 return false, errors.Wrap(err, "failed to update Job") 62 } 63 64 rows, err := sqlResult.RowsAffected() 65 66 if err != nil { 67 return false, errors.Wrap(err, "unable to get rows affected") 68 } 69 70 if rows != 1 { 71 return false, nil 72 } 73 74 return true, nil 75 } 76 77 func (jss SqlJobStore) UpdateStatus(id string, status string) (*model.Job, error) { 78 job := &model.Job{ 79 Id: id, 80 Status: status, 81 LastActivityAt: model.GetMillis(), 82 } 83 84 if _, err := jss.GetMaster().UpdateColumns(func(col *gorp.ColumnMap) bool { 85 return col.ColumnName == "Status" || col.ColumnName == "LastActivityAt" 86 }, job); err != nil { 87 return nil, errors.Wrapf(err, "failed to update Job with id=%s", id) 88 } 89 90 return job, nil 91 } 92 93 func (jss SqlJobStore) UpdateStatusOptimistically(id string, currentStatus string, newStatus string) (bool, error) { 94 builder := jss.getQueryBuilder(). 95 Update("Jobs"). 96 Set("LastActivityAt", model.GetMillis()). 97 Set("Status", newStatus). 98 Where(sq.Eq{"Id": id, "Status": currentStatus}) 99 100 if newStatus == model.JOB_STATUS_IN_PROGRESS { 101 builder = builder.Set("StartAt", model.GetMillis()) 102 } 103 query, args, err := builder.ToSql() 104 if err != nil { 105 return false, errors.Wrap(err, "job_tosql") 106 } 107 108 sqlResult, err := jss.GetMaster().Exec(query, args...) 109 if err != nil { 110 return false, errors.Wrapf(err, "failed to update Job with id=%s", id) 111 } 112 rows, err := sqlResult.RowsAffected() 113 if err != nil { 114 return false, errors.Wrap(err, "unable to get rows affected") 115 } 116 if rows != 1 { 117 return false, nil 118 } 119 120 return true, nil 121 } 122 123 func (jss SqlJobStore) Get(id string) (*model.Job, error) { 124 query, args, err := jss.getQueryBuilder(). 125 Select("*"). 126 From("Jobs"). 127 Where(sq.Eq{"Id": id}).ToSql() 128 if err != nil { 129 return nil, errors.Wrap(err, "job_tosql") 130 } 131 var status *model.Job 132 if err = jss.GetReplica().SelectOne(&status, query, args...); err != nil { 133 if err == sql.ErrNoRows { 134 return nil, store.NewErrNotFound("Job", id) 135 } 136 return nil, errors.Wrapf(err, "failed to get Job with id=%s", id) 137 } 138 return status, nil 139 } 140 141 func (jss SqlJobStore) GetAllPage(offset int, limit int) ([]*model.Job, error) { 142 query, args, err := jss.getQueryBuilder(). 143 Select("*"). 144 From("Jobs"). 145 OrderBy("CreateAt DESC"). 146 Limit(uint64(limit)). 147 Offset(uint64(offset)).ToSql() 148 if err != nil { 149 return nil, errors.Wrap(err, "job_tosql") 150 } 151 152 var statuses []*model.Job 153 if _, err = jss.GetReplica().Select(&statuses, query, args...); err != nil { 154 return nil, errors.Wrap(err, "failed to find Jobs") 155 } 156 return statuses, nil 157 } 158 159 func (jss SqlJobStore) GetAllByTypesPage(jobTypes []string, offset int, limit int) ([]*model.Job, error) { 160 query, args, err := jss.getQueryBuilder(). 161 Select("*"). 162 From("Jobs"). 163 Where(sq.Eq{"Type": jobTypes}). 164 OrderBy("CreateAt DESC"). 165 Limit(uint64(limit)). 166 Offset(uint64(offset)).ToSql() 167 if err != nil { 168 return nil, errors.Wrap(err, "job_tosql") 169 } 170 171 var jobs []*model.Job 172 if _, err = jss.GetReplica().Select(&jobs, query, args...); err != nil { 173 return nil, errors.Wrapf(err, "failed to find Jobs with types") 174 } 175 return jobs, nil 176 } 177 178 func (jss SqlJobStore) GetAllByType(jobType string) ([]*model.Job, error) { 179 query, args, err := jss.getQueryBuilder(). 180 Select("*"). 181 From("Jobs"). 182 Where(sq.Eq{"Type": jobType}). 183 OrderBy("CreateAt DESC").ToSql() 184 if err != nil { 185 return nil, errors.Wrap(err, "job_tosql") 186 } 187 var statuses []*model.Job 188 if _, err = jss.GetReplica().Select(&statuses, query, args...); err != nil { 189 return nil, errors.Wrapf(err, "failed to find Jobs with type=%s", jobType) 190 } 191 return statuses, nil 192 } 193 194 func (jss SqlJobStore) GetAllByTypePage(jobType string, offset int, limit int) ([]*model.Job, error) { 195 query, args, err := jss.getQueryBuilder(). 196 Select("*"). 197 From("Jobs"). 198 Where(sq.Eq{"Type": jobType}). 199 OrderBy("CreateAt DESC"). 200 Limit(uint64(limit)). 201 Offset(uint64(offset)).ToSql() 202 if err != nil { 203 return nil, errors.Wrap(err, "job_tosql") 204 } 205 206 var statuses []*model.Job 207 if _, err = jss.GetReplica().Select(&statuses, query, args...); err != nil { 208 return nil, errors.Wrapf(err, "failed to find Jobs with type=%s", jobType) 209 } 210 return statuses, nil 211 } 212 213 func (jss SqlJobStore) GetAllByStatus(status string) ([]*model.Job, error) { 214 var statuses []*model.Job 215 query, args, err := jss.getQueryBuilder(). 216 Select("*"). 217 From("Jobs"). 218 Where(sq.Eq{"Status": status}). 219 OrderBy("CreateAt ASC").ToSql() 220 if err != nil { 221 return nil, errors.Wrap(err, "job_tosql") 222 } 223 224 if _, err = jss.GetReplica().Select(&statuses, query, args...); err != nil { 225 return nil, errors.Wrapf(err, "failed to find Jobs with status=%s", status) 226 } 227 return statuses, nil 228 } 229 230 func (jss SqlJobStore) GetNewestJobByStatusAndType(status string, jobType string) (*model.Job, error) { 231 return jss.GetNewestJobByStatusesAndType([]string{status}, jobType) 232 } 233 234 func (jss SqlJobStore) GetNewestJobByStatusesAndType(status []string, jobType string) (*model.Job, error) { 235 query, args, err := jss.getQueryBuilder(). 236 Select("*"). 237 From("Jobs"). 238 Where(sq.Eq{"Status": status, "Type": jobType}). 239 OrderBy("CreateAt DESC"). 240 Limit(1).ToSql() 241 if err != nil { 242 return nil, errors.Wrap(err, "job_tosql") 243 } 244 245 var job *model.Job 246 if err = jss.GetReplica().SelectOne(&job, query, args...); err != nil { 247 if err == sql.ErrNoRows { 248 return nil, store.NewErrNotFound("Job", fmt.Sprintf("<status, type>=<%s, %s>", strings.Join(status, ","), jobType)) 249 } 250 return nil, errors.Wrapf(err, "failed to find Job with statuses=%s and type=%s", strings.Join(status, ","), jobType) 251 } 252 return job, nil 253 } 254 255 func (jss SqlJobStore) GetCountByStatusAndType(status string, jobType string) (int64, error) { 256 query, args, err := jss.getQueryBuilder(). 257 Select("COUNT(*)"). 258 From("Jobs"). 259 Where(sq.Eq{"Status": status, "Type": jobType}).ToSql() 260 if err != nil { 261 return 0, errors.Wrap(err, "job_tosql") 262 } 263 count, err := jss.GetReplica().SelectInt(query, args...) 264 if err != nil { 265 return int64(0), errors.Wrapf(err, "failed to count Jobs with status=%s and type=%s", status, jobType) 266 } 267 return count, nil 268 } 269 270 func (jss SqlJobStore) Delete(id string) (string, error) { 271 query, args, err := jss.getQueryBuilder(). 272 Delete("Jobs"). 273 Where(sq.Eq{"Id": id}).ToSql() 274 if err != nil { 275 return "", errors.Wrap(err, "job_tosql") 276 } 277 278 if _, err = jss.GetMaster().Exec(query, args...); err != nil { 279 return "", errors.Wrapf(err, "failed to delete Job with id=%s", id) 280 } 281 return id, nil 282 }