github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/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  	sq "github.com/Masterminds/squirrel"
    11  
    12  	"github.com/mattermost/gorp"
    13  	"github.com/mattermost/mattermost-server/v5/model"
    14  	"github.com/mattermost/mattermost-server/v5/store"
    15  )
    16  
    17  type SqlJobStore struct {
    18  	SqlStore
    19  }
    20  
    21  func newSqlJobStore(sqlStore SqlStore) store.JobStore {
    22  	s := &SqlJobStore{sqlStore}
    23  
    24  	for _, db := range sqlStore.GetAllConns() {
    25  		table := db.AddTableWithName(model.Job{}, "Jobs").SetKeys(false, "Id")
    26  		table.ColMap("Id").SetMaxSize(26)
    27  		table.ColMap("Type").SetMaxSize(32)
    28  		table.ColMap("Status").SetMaxSize(32)
    29  		table.ColMap("Data").SetMaxSize(1024)
    30  	}
    31  
    32  	return s
    33  }
    34  
    35  func (jss SqlJobStore) createIndexesIfNotExists() {
    36  	jss.CreateIndexIfNotExists("idx_jobs_type", "Jobs", "Type")
    37  }
    38  
    39  func (jss SqlJobStore) Save(job *model.Job) (*model.Job, *model.AppError) {
    40  	if err := jss.GetMaster().Insert(job); err != nil {
    41  		return nil, model.NewAppError("SqlJobStore.Save", "store.sql_job.save.app_error", nil, "id="+job.Id+", "+err.Error(), http.StatusInternalServerError)
    42  	}
    43  	return job, nil
    44  }
    45  
    46  func (jss SqlJobStore) UpdateOptimistically(job *model.Job, currentStatus string) (bool, *model.AppError) {
    47  	sql, args, err := jss.getQueryBuilder().
    48  		Update("Jobs").
    49  		Set("LastActivityAt", model.GetMillis()).
    50  		Set("Status", job.Status).
    51  		Set("Data", job.DataToJson()).
    52  		Set("Progress", job.Progress).
    53  		Where(sq.Eq{"Id": job.Id, "Status": currentStatus}).ToSql()
    54  	if err != nil {
    55  		return false, model.NewAppError("SqlJobStore.UpdateOptimistically", "store.sql.build_query.app_error", nil, err.Error(), http.StatusInternalServerError)
    56  	}
    57  	sqlResult, err := jss.GetMaster().Exec(sql, args...)
    58  	if err != nil {
    59  		return false, model.NewAppError("SqlJobStore.UpdateOptimistically", "store.sql_job.update.app_error", nil, "id="+job.Id+", "+err.Error(), http.StatusInternalServerError)
    60  	}
    61  
    62  	rows, err := sqlResult.RowsAffected()
    63  
    64  	if err != nil {
    65  		return false, model.NewAppError("SqlJobStore.UpdateStatus", "store.sql_job.update.app_error", nil, "id="+job.Id+", "+err.Error(), http.StatusInternalServerError)
    66  	}
    67  
    68  	if rows != 1 {
    69  		return false, nil
    70  	}
    71  
    72  	return true, nil
    73  }
    74  
    75  func (jss SqlJobStore) UpdateStatus(id string, status string) (*model.Job, *model.AppError) {
    76  	job := &model.Job{
    77  		Id:             id,
    78  		Status:         status,
    79  		LastActivityAt: model.GetMillis(),
    80  	}
    81  
    82  	if _, err := jss.GetMaster().UpdateColumns(func(col *gorp.ColumnMap) bool {
    83  		return col.ColumnName == "Status" || col.ColumnName == "LastActivityAt"
    84  	}, job); err != nil {
    85  		return nil, model.NewAppError("SqlJobStore.UpdateStatus", "store.sql_job.update.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError)
    86  	}
    87  
    88  	return job, nil
    89  }
    90  
    91  func (jss SqlJobStore) UpdateStatusOptimistically(id string, currentStatus string, newStatus string) (bool, *model.AppError) {
    92  	sql := jss.getQueryBuilder().
    93  		Update("Jobs").
    94  		Set("LastActivityAt", model.GetMillis()).
    95  		Set("Status", newStatus).
    96  		Where(sq.Eq{"Id": id, "Status": currentStatus})
    97  
    98  	if newStatus == model.JOB_STATUS_IN_PROGRESS {
    99  		sql = sql.Set("StartAt", model.GetMillis())
   100  	}
   101  	query, args, err := sql.ToSql()
   102  	if err != nil {
   103  		return false, model.NewAppError("SqlJobStore.UpdateStatusOptimistically", "store.sql.build_query.app_error", nil, err.Error(), http.StatusInternalServerError)
   104  	}
   105  
   106  	sqlResult, err := jss.GetMaster().Exec(query, args...)
   107  	if err != nil {
   108  		return false, model.NewAppError("SqlJobStore.UpdateStatusOptimistically", "store.sql_job.update.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError)
   109  	}
   110  	rows, err := sqlResult.RowsAffected()
   111  	if err != nil {
   112  		return false, model.NewAppError("SqlJobStore.UpdateStatus", "store.sql_job.update.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError)
   113  	}
   114  	if rows != 1 {
   115  		return false, nil
   116  	}
   117  
   118  	return true, nil
   119  }
   120  
   121  func (jss SqlJobStore) Get(id string) (*model.Job, *model.AppError) {
   122  	query, args, err := jss.getQueryBuilder().
   123  		Select("*").
   124  		From("Jobs").
   125  		Where(sq.Eq{"Id": id}).ToSql()
   126  	if err != nil {
   127  		return nil, model.NewAppError("SqlJobStore.Get", "store.sql.build_query.app_error", nil, err.Error(), http.StatusInternalServerError)
   128  	}
   129  	var status *model.Job
   130  	if err = jss.GetReplica().SelectOne(&status, query, args...); err != nil {
   131  		if err == sql.ErrNoRows {
   132  			return nil, model.NewAppError("SqlJobStore.Get", "store.sql_job.get.app_error", nil, "Id="+id+", "+err.Error(), http.StatusNotFound)
   133  		}
   134  		return nil, model.NewAppError("SqlJobStore.Get", "store.sql_job.get.app_error", nil, "Id="+id+", "+err.Error(), http.StatusInternalServerError)
   135  	}
   136  	return status, nil
   137  }
   138  
   139  func (jss SqlJobStore) GetAllPage(offset int, limit int) ([]*model.Job, *model.AppError) {
   140  	query, args, err := jss.getQueryBuilder().
   141  		Select("*").
   142  		From("Jobs").
   143  		OrderBy("CreateAt DESC").
   144  		Limit(uint64(limit)).
   145  		Offset(uint64(offset)).ToSql()
   146  	if err != nil {
   147  		return nil, model.NewAppError("SqlJobStore.GetAllPage", "store.sql.build_query.app_error", nil, err.Error(), http.StatusInternalServerError)
   148  	}
   149  
   150  	var statuses []*model.Job
   151  	if _, err = jss.GetReplica().Select(&statuses, query, args...); err != nil {
   152  		return nil, model.NewAppError("SqlJobStore.GetAllPage", "store.sql_job.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   153  	}
   154  	return statuses, nil
   155  }
   156  
   157  func (jss SqlJobStore) GetAllByType(jobType string) ([]*model.Job, *model.AppError) {
   158  	query, args, err := jss.getQueryBuilder().
   159  		Select("*").
   160  		From("Jobs").
   161  		Where(sq.Eq{"Type": jobType}).
   162  		OrderBy("CreateAt DESC").ToSql()
   163  	if err != nil {
   164  		return nil, model.NewAppError("SqlJobStore.GetAllByType", "store.sql.build_query.app_error", nil, err.Error(), http.StatusInternalServerError)
   165  	}
   166  	var statuses []*model.Job
   167  	if _, err = jss.GetReplica().Select(&statuses, query, args...); err != nil {
   168  		return nil, model.NewAppError("SqlJobStore.GetAllByType", "store.sql_job.get_all.app_error", nil, "Type="+jobType+", "+err.Error(), http.StatusInternalServerError)
   169  	}
   170  	return statuses, nil
   171  }
   172  
   173  func (jss SqlJobStore) GetAllByTypePage(jobType string, offset int, limit int) ([]*model.Job, *model.AppError) {
   174  	query, args, err := jss.getQueryBuilder().
   175  		Select("*").
   176  		From("Jobs").
   177  		Where(sq.Eq{"Type": jobType}).
   178  		OrderBy("CreateAt DESC").
   179  		Limit(uint64(limit)).
   180  		Offset(uint64(offset)).ToSql()
   181  	if err != nil {
   182  		return nil, model.NewAppError("SqlJobStore.GetAllByTypePage", "store.sql.build_query.app_error", nil, err.Error(), http.StatusInternalServerError)
   183  	}
   184  
   185  	var statuses []*model.Job
   186  	if _, err = jss.GetReplica().Select(&statuses, query, args...); err != nil {
   187  		return nil, model.NewAppError("SqlJobStore.GetAllByTypePage", "store.sql_job.get_all.app_error", nil, "Type="+jobType+", "+err.Error(), http.StatusInternalServerError)
   188  	}
   189  	return statuses, nil
   190  }
   191  
   192  func (jss SqlJobStore) GetAllByStatus(status string) ([]*model.Job, *model.AppError) {
   193  	var statuses []*model.Job
   194  	query, args, err := jss.getQueryBuilder().
   195  		Select("*").
   196  		From("Jobs").
   197  		Where(sq.Eq{"Status": status}).
   198  		OrderBy("CreateAt ASC").ToSql()
   199  	if err != nil {
   200  		return nil, model.NewAppError("SqlJobStore.GetAllByStatus", "store.sql.build_query.app_error", nil, err.Error(), http.StatusInternalServerError)
   201  	}
   202  
   203  	if _, err = jss.GetReplica().Select(&statuses, query, args...); err != nil {
   204  		return nil, model.NewAppError("SqlJobStore.GetAllByStatus", "store.sql_job.get_all.app_error", nil, "Status="+status+", "+err.Error(), http.StatusInternalServerError)
   205  	}
   206  	return statuses, nil
   207  }
   208  
   209  func (jss SqlJobStore) GetNewestJobByStatusAndType(status string, jobType string) (*model.Job, *model.AppError) {
   210  	query, args, err := jss.getQueryBuilder().
   211  		Select("*").
   212  		From("Jobs").
   213  		Where(sq.Eq{"Status": status, "Type": jobType}).
   214  		OrderBy("CreateAt DESC").
   215  		Limit(1).ToSql()
   216  	if err != nil {
   217  		return nil, model.NewAppError("SqlJobStore.GetNewestJobByStatusAndType", "store.sql.build_query.app_error", nil, err.Error(), http.StatusInternalServerError)
   218  	}
   219  
   220  	var job *model.Job
   221  	if err = jss.GetReplica().SelectOne(&job, query, args...); err != nil && err != sql.ErrNoRows {
   222  		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)
   223  	}
   224  	return job, nil
   225  }
   226  
   227  func (jss SqlJobStore) GetCountByStatusAndType(status string, jobType string) (int64, *model.AppError) {
   228  	query, args, err := jss.getQueryBuilder().
   229  		Select("COUNT(*)").
   230  		From("Jobs").
   231  		Where(sq.Eq{"Status": status, "Type": jobType}).ToSql()
   232  	if err != nil {
   233  		return 0, model.NewAppError("SqlJobStore.GetCountByStatusAndType", "store.sql.build_query.app_error", nil, err.Error(), http.StatusInternalServerError)
   234  	}
   235  	count, err := jss.GetReplica().SelectInt(query, args...)
   236  	if err != nil {
   237  		return int64(0), model.NewAppError("SqlJobStore.GetCountByStatusAndType", "store.sql_job.get_count_by_status_and_type.app_error", nil, "Status="+status+", "+err.Error(), http.StatusInternalServerError)
   238  	}
   239  	return count, nil
   240  }
   241  
   242  func (jss SqlJobStore) Delete(id string) (string, *model.AppError) {
   243  	sql, args, err := jss.getQueryBuilder().
   244  		Delete("Jobs").
   245  		Where(sq.Eq{"Id": id}).ToSql()
   246  	if err != nil {
   247  		return "", model.NewAppError("SqlJobStore.DeleteByType", "store.sql.build_query.app_error", nil, err.Error(), http.StatusInternalServerError)
   248  	}
   249  
   250  	if _, err = jss.GetMaster().Exec(sql, args...); err != nil {
   251  		return "", model.NewAppError("SqlJobStore.DeleteByType", "store.sql_job.delete.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError)
   252  	}
   253  	return id, nil
   254  }