github.com/qichengzx/mattermost-server@v4.5.1-0.20180604164826-2c75247c97d0+incompatible/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 "net/http" 9 10 "github.com/mattermost/gorp" 11 "github.com/mattermost/mattermost-server/model" 12 "github.com/mattermost/mattermost-server/store" 13 ) 14 15 type SqlJobStore struct { 16 SqlStore 17 } 18 19 func NewSqlJobStore(sqlStore SqlStore) store.JobStore { 20 s := &SqlJobStore{sqlStore} 21 22 for _, db := range sqlStore.GetAllConns() { 23 table := db.AddTableWithName(model.Job{}, "Jobs").SetKeys(false, "Id") 24 table.ColMap("Id").SetMaxSize(26) 25 table.ColMap("Type").SetMaxSize(32) 26 table.ColMap("Status").SetMaxSize(32) 27 table.ColMap("Data").SetMaxSize(1024) 28 } 29 30 return s 31 } 32 33 func (jss SqlJobStore) CreateIndexesIfNotExists() { 34 jss.CreateIndexIfNotExists("idx_jobs_type", "Jobs", "Type") 35 } 36 37 func (jss SqlJobStore) Save(job *model.Job) store.StoreChannel { 38 return store.Do(func(result *store.StoreResult) { 39 if err := jss.GetMaster().Insert(job); err != nil { 40 result.Err = model.NewAppError("SqlJobStore.Save", "store.sql_job.save.app_error", nil, "id="+job.Id+", "+err.Error(), http.StatusInternalServerError) 41 } else { 42 result.Data = job 43 } 44 }) 45 } 46 47 func (jss SqlJobStore) UpdateOptimistically(job *model.Job, currentStatus string) store.StoreChannel { 48 return store.Do(func(result *store.StoreResult) { 49 if sqlResult, err := jss.GetMaster().Exec( 50 `UPDATE 51 Jobs 52 SET 53 LastActivityAt = :LastActivityAt, 54 Status = :Status, 55 Progress = :Progress, 56 Data = :Data 57 WHERE 58 Id = :Id 59 AND 60 Status = :OldStatus`, 61 map[string]interface{}{ 62 "Id": job.Id, 63 "OldStatus": currentStatus, 64 "LastActivityAt": model.GetMillis(), 65 "Status": job.Status, 66 "Data": job.DataToJson(), 67 "Progress": job.Progress, 68 }); err != nil { 69 result.Err = model.NewAppError("SqlJobStore.UpdateOptimistically", "store.sql_job.update.app_error", nil, "id="+job.Id+", "+err.Error(), http.StatusInternalServerError) 70 } else { 71 rows, err := sqlResult.RowsAffected() 72 73 if err != nil { 74 result.Err = model.NewAppError("SqlJobStore.UpdateStatus", "store.sql_job.update.app_error", nil, "id="+job.Id+", "+err.Error(), http.StatusInternalServerError) 75 } else { 76 if rows == 1 { 77 result.Data = true 78 } else { 79 result.Data = false 80 } 81 } 82 } 83 }) 84 } 85 86 func (jss SqlJobStore) UpdateStatus(id string, status string) store.StoreChannel { 87 return store.Do(func(result *store.StoreResult) { 88 job := &model.Job{ 89 Id: id, 90 Status: status, 91 LastActivityAt: model.GetMillis(), 92 } 93 94 if _, err := jss.GetMaster().UpdateColumns(func(col *gorp.ColumnMap) bool { 95 return col.ColumnName == "Status" || col.ColumnName == "LastActivityAt" 96 }, job); err != nil { 97 result.Err = model.NewAppError("SqlJobStore.UpdateStatus", "store.sql_job.update.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError) 98 } 99 100 if result.Err == nil { 101 result.Data = job 102 } 103 }) 104 } 105 106 func (jss SqlJobStore) UpdateStatusOptimistically(id string, currentStatus string, newStatus string) store.StoreChannel { 107 return store.Do(func(result *store.StoreResult) { 108 var startAtClause string 109 if newStatus == model.JOB_STATUS_IN_PROGRESS { 110 startAtClause = `StartAt = :StartAt,` 111 } 112 113 if sqlResult, err := jss.GetMaster().Exec( 114 `UPDATE 115 Jobs 116 SET `+startAtClause+` 117 Status = :NewStatus, 118 LastActivityAt = :LastActivityAt 119 WHERE 120 Id = :Id 121 AND 122 Status = :OldStatus`, map[string]interface{}{"Id": id, "OldStatus": currentStatus, "NewStatus": newStatus, "StartAt": model.GetMillis(), "LastActivityAt": model.GetMillis()}); err != nil { 123 result.Err = model.NewAppError("SqlJobStore.UpdateStatus", "store.sql_job.update.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError) 124 } else { 125 rows, err := sqlResult.RowsAffected() 126 127 if err != nil { 128 result.Err = model.NewAppError("SqlJobStore.UpdateStatus", "store.sql_job.update.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError) 129 } else { 130 if rows == 1 { 131 result.Data = true 132 } else { 133 result.Data = false 134 } 135 } 136 } 137 }) 138 } 139 140 func (jss SqlJobStore) Get(id string) store.StoreChannel { 141 return store.Do(func(result *store.StoreResult) { 142 var status *model.Job 143 144 if err := jss.GetReplica().SelectOne(&status, 145 `SELECT 146 * 147 FROM 148 Jobs 149 WHERE 150 Id = :Id`, map[string]interface{}{"Id": id}); err != nil { 151 if err == sql.ErrNoRows { 152 result.Err = model.NewAppError("SqlJobStore.Get", "store.sql_job.get.app_error", nil, "Id="+id+", "+err.Error(), http.StatusNotFound) 153 } else { 154 result.Err = model.NewAppError("SqlJobStore.Get", "store.sql_job.get.app_error", nil, "Id="+id+", "+err.Error(), http.StatusInternalServerError) 155 } 156 } else { 157 result.Data = status 158 } 159 }) 160 } 161 162 func (jss SqlJobStore) GetAllPage(offset int, limit int) store.StoreChannel { 163 return store.Do(func(result *store.StoreResult) { 164 var statuses []*model.Job 165 166 if _, err := jss.GetReplica().Select(&statuses, 167 `SELECT 168 * 169 FROM 170 Jobs 171 ORDER BY 172 CreateAt DESC 173 LIMIT 174 :Limit 175 OFFSET 176 :Offset`, map[string]interface{}{"Limit": limit, "Offset": offset}); err != nil { 177 result.Err = model.NewAppError("SqlJobStore.GetAllPage", "store.sql_job.get_all.app_error", nil, err.Error(), http.StatusInternalServerError) 178 } else { 179 result.Data = statuses 180 } 181 }) 182 } 183 184 func (jss SqlJobStore) GetAllByType(jobType string) store.StoreChannel { 185 return store.Do(func(result *store.StoreResult) { 186 var statuses []*model.Job 187 188 if _, err := jss.GetReplica().Select(&statuses, 189 `SELECT 190 * 191 FROM 192 Jobs 193 WHERE 194 Type = :Type 195 ORDER BY 196 CreateAt DESC`, map[string]interface{}{"Type": jobType}); err != nil { 197 result.Err = model.NewAppError("SqlJobStore.GetAllByType", "store.sql_job.get_all.app_error", nil, "Type="+jobType+", "+err.Error(), http.StatusInternalServerError) 198 } else { 199 result.Data = statuses 200 } 201 }) 202 } 203 204 func (jss SqlJobStore) GetAllByTypePage(jobType string, offset int, limit int) store.StoreChannel { 205 return store.Do(func(result *store.StoreResult) { 206 var statuses []*model.Job 207 208 if _, err := jss.GetReplica().Select(&statuses, 209 `SELECT 210 * 211 FROM 212 Jobs 213 WHERE 214 Type = :Type 215 ORDER BY 216 CreateAt DESC 217 LIMIT 218 :Limit 219 OFFSET 220 :Offset`, map[string]interface{}{"Type": jobType, "Limit": limit, "Offset": offset}); err != nil { 221 result.Err = model.NewAppError("SqlJobStore.GetAllByTypePage", "store.sql_job.get_all.app_error", nil, "Type="+jobType+", "+err.Error(), http.StatusInternalServerError) 222 } else { 223 result.Data = statuses 224 } 225 }) 226 } 227 228 func (jss SqlJobStore) GetAllByStatus(status string) store.StoreChannel { 229 return store.Do(func(result *store.StoreResult) { 230 var statuses []*model.Job 231 232 if _, err := jss.GetReplica().Select(&statuses, 233 `SELECT 234 * 235 FROM 236 Jobs 237 WHERE 238 Status = :Status 239 ORDER BY 240 CreateAt ASC`, map[string]interface{}{"Status": status}); err != nil { 241 result.Err = model.NewAppError("SqlJobStore.GetAllByStatus", "store.sql_job.get_all.app_error", nil, "Status="+status+", "+err.Error(), http.StatusInternalServerError) 242 } else { 243 result.Data = statuses 244 } 245 }) 246 } 247 248 func (jss SqlJobStore) GetNewestJobByStatusAndType(status string, jobType string) store.StoreChannel { 249 return store.Do(func(result *store.StoreResult) { 250 var job *model.Job 251 252 if err := jss.GetReplica().SelectOne(&job, 253 `SELECT 254 * 255 FROM 256 Jobs 257 WHERE 258 Status = :Status 259 AND 260 Type = :Type 261 ORDER BY 262 CreateAt DESC 263 LIMIT 1`, map[string]interface{}{"Status": status, "Type": jobType}); err != nil && err != sql.ErrNoRows { 264 result.Err = model.NewAppError("SqlJobStore.GetNewestJobByStatusAndType", "store.sql_job.get_newest_job_by_status_and_type.app_error", nil, "Status="+status+", "+err.Error(), http.StatusInternalServerError) 265 } else { 266 result.Data = job 267 } 268 }) 269 } 270 271 func (jss SqlJobStore) GetCountByStatusAndType(status string, jobType string) store.StoreChannel { 272 return store.Do(func(result *store.StoreResult) { 273 if count, err := jss.GetReplica().SelectInt(`SELECT 274 COUNT(*) 275 FROM 276 Jobs 277 WHERE 278 Status = :Status 279 AND 280 Type = :Type`, map[string]interface{}{"Status": status, "Type": jobType}); err != nil { 281 result.Err = model.NewAppError("SqlJobStore.GetCountByStatusAndType", "store.sql_job.get_count_by_status_and_type.app_error", nil, "Status="+status+", "+err.Error(), http.StatusInternalServerError) 282 } else { 283 result.Data = count 284 } 285 }) 286 } 287 288 func (jss SqlJobStore) Delete(id string) store.StoreChannel { 289 return store.Do(func(result *store.StoreResult) { 290 if _, err := jss.GetMaster().Exec( 291 `DELETE FROM 292 Jobs 293 WHERE 294 Id = :Id`, map[string]interface{}{"Id": id}); err != nil { 295 result.Err = model.NewAppError("SqlJobStore.DeleteByType", "store.sql_job.delete.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError) 296 } else { 297 result.Data = id 298 } 299 }) 300 }