github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/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/mattermost/mattermost-server/v5/model" 16 "github.com/mattermost/mattermost-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) GetAllByType(jobType string) ([]*model.Job, error) { 160 query, args, err := jss.getQueryBuilder(). 161 Select("*"). 162 From("Jobs"). 163 Where(sq.Eq{"Type": jobType}). 164 OrderBy("CreateAt DESC").ToSql() 165 if err != nil { 166 return nil, errors.Wrap(err, "job_tosql") 167 } 168 var statuses []*model.Job 169 if _, err = jss.GetReplica().Select(&statuses, query, args...); err != nil { 170 return nil, errors.Wrapf(err, "failed to find Jobs with type=%s", jobType) 171 } 172 return statuses, nil 173 } 174 175 func (jss SqlJobStore) GetAllByTypePage(jobType string, offset int, limit int) ([]*model.Job, error) { 176 query, args, err := jss.getQueryBuilder(). 177 Select("*"). 178 From("Jobs"). 179 Where(sq.Eq{"Type": jobType}). 180 OrderBy("CreateAt DESC"). 181 Limit(uint64(limit)). 182 Offset(uint64(offset)).ToSql() 183 if err != nil { 184 return nil, errors.Wrap(err, "job_tosql") 185 } 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) GetAllByStatus(status string) ([]*model.Job, error) { 195 var statuses []*model.Job 196 query, args, err := jss.getQueryBuilder(). 197 Select("*"). 198 From("Jobs"). 199 Where(sq.Eq{"Status": status}). 200 OrderBy("CreateAt ASC").ToSql() 201 if err != nil { 202 return nil, errors.Wrap(err, "job_tosql") 203 } 204 205 if _, err = jss.GetReplica().Select(&statuses, query, args...); err != nil { 206 return nil, errors.Wrapf(err, "failed to find Jobs with status=%s", status) 207 } 208 return statuses, nil 209 } 210 211 func (jss SqlJobStore) GetNewestJobByStatusAndType(status string, jobType string) (*model.Job, error) { 212 return jss.GetNewestJobByStatusesAndType([]string{status}, jobType) 213 } 214 215 func (jss SqlJobStore) GetNewestJobByStatusesAndType(status []string, jobType string) (*model.Job, error) { 216 query, args, err := jss.getQueryBuilder(). 217 Select("*"). 218 From("Jobs"). 219 Where(sq.Eq{"Status": status, "Type": jobType}). 220 OrderBy("CreateAt DESC"). 221 Limit(1).ToSql() 222 if err != nil { 223 return nil, errors.Wrap(err, "job_tosql") 224 } 225 226 var job *model.Job 227 if err = jss.GetReplica().SelectOne(&job, query, args...); err != nil { 228 if err == sql.ErrNoRows { 229 return nil, store.NewErrNotFound("Job", fmt.Sprintf("<status, type>=<%s, %s>", strings.Join(status, ","), jobType)) 230 } 231 return nil, errors.Wrapf(err, "failed to find Job with statuses=%s and type=%s", strings.Join(status, ","), jobType) 232 } 233 return job, nil 234 } 235 236 func (jss SqlJobStore) GetCountByStatusAndType(status string, jobType string) (int64, error) { 237 query, args, err := jss.getQueryBuilder(). 238 Select("COUNT(*)"). 239 From("Jobs"). 240 Where(sq.Eq{"Status": status, "Type": jobType}).ToSql() 241 if err != nil { 242 return 0, errors.Wrap(err, "job_tosql") 243 } 244 count, err := jss.GetReplica().SelectInt(query, args...) 245 if err != nil { 246 return int64(0), errors.Wrapf(err, "failed to count Jobs with status=%s and type=%s", status, jobType) 247 } 248 return count, nil 249 } 250 251 func (jss SqlJobStore) Delete(id string) (string, error) { 252 query, args, err := jss.getQueryBuilder(). 253 Delete("Jobs"). 254 Where(sq.Eq{"Id": id}).ToSql() 255 if err != nil { 256 return "", errors.Wrap(err, "job_tosql") 257 } 258 259 if _, err = jss.GetMaster().Exec(query, args...); err != nil { 260 return "", errors.Wrapf(err, "failed to delete Job with id=%s", id) 261 } 262 return id, nil 263 }