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  }