github.com/haalcala/mattermost-server-change-repo@v0.0.0-20210713015153-16753fbeee5f/jobs/export_process/worker.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package export_process
     5  
     6  import (
     7  	"io"
     8  	"path/filepath"
     9  
    10  	"github.com/mattermost/mattermost-server/v5/app"
    11  	"github.com/mattermost/mattermost-server/v5/jobs"
    12  	tjobs "github.com/mattermost/mattermost-server/v5/jobs/interfaces"
    13  	"github.com/mattermost/mattermost-server/v5/mlog"
    14  	"github.com/mattermost/mattermost-server/v5/model"
    15  )
    16  
    17  func init() {
    18  	app.RegisterJobsExportProcessInterface(func(a *app.App) tjobs.ExportProcessInterface {
    19  		return &ExportProcessInterfaceImpl{a}
    20  	})
    21  }
    22  
    23  type ExportProcessInterfaceImpl struct {
    24  	app *app.App
    25  }
    26  
    27  type ExportProcessWorker struct {
    28  	name        string
    29  	stopChan    chan struct{}
    30  	stoppedChan chan struct{}
    31  	jobsChan    chan model.Job
    32  	jobServer   *jobs.JobServer
    33  	app         *app.App
    34  }
    35  
    36  func (i *ExportProcessInterfaceImpl) MakeWorker() model.Worker {
    37  	return &ExportProcessWorker{
    38  		name:        "ExportProcess",
    39  		stopChan:    make(chan struct{}),
    40  		stoppedChan: make(chan struct{}),
    41  		jobsChan:    make(chan model.Job),
    42  		jobServer:   i.app.Srv().Jobs,
    43  		app:         i.app,
    44  	}
    45  }
    46  
    47  func (w *ExportProcessWorker) JobChannel() chan<- model.Job {
    48  	return w.jobsChan
    49  }
    50  
    51  func (w *ExportProcessWorker) Run() {
    52  	mlog.Debug("Worker started", mlog.String("worker", w.name))
    53  
    54  	defer func() {
    55  		mlog.Debug("Worker finished", mlog.String("worker", w.name))
    56  		close(w.stoppedChan)
    57  	}()
    58  
    59  	for {
    60  		select {
    61  		case <-w.stopChan:
    62  			mlog.Debug("Worker received stop signal", mlog.String("worker", w.name))
    63  			return
    64  		case job := <-w.jobsChan:
    65  			mlog.Debug("Worker received a new candidate job.", mlog.String("worker", w.name))
    66  			w.doJob(&job)
    67  		}
    68  	}
    69  }
    70  
    71  func (w *ExportProcessWorker) Stop() {
    72  	mlog.Debug("Worker stopping", mlog.String("worker", w.name))
    73  	close(w.stopChan)
    74  	<-w.stoppedChan
    75  }
    76  
    77  func (w *ExportProcessWorker) doJob(job *model.Job) {
    78  	if claimed, err := w.jobServer.ClaimJob(job); err != nil {
    79  		mlog.Warn("Worker experienced an error while trying to claim job",
    80  			mlog.String("worker", w.name),
    81  			mlog.String("job_id", job.Id),
    82  			mlog.String("error", err.Error()))
    83  		return
    84  	} else if !claimed {
    85  		return
    86  	}
    87  
    88  	opts := app.BulkExportOpts{
    89  		CreateArchive: true,
    90  	}
    91  
    92  	includeAttachments, ok := job.Data["include_attachments"]
    93  	if ok && includeAttachments == "true" {
    94  		opts.IncludeAttachments = true
    95  	}
    96  
    97  	outPath := *w.app.Config().ExportSettings.Directory
    98  	exportFilename := model.NewId() + "_export.zip"
    99  
   100  	rd, wr := io.Pipe()
   101  
   102  	errCh := make(chan *model.AppError, 1)
   103  	go func() {
   104  		defer close(errCh)
   105  		_, appErr := w.app.WriteFile(rd, filepath.Join(outPath, exportFilename))
   106  		errCh <- appErr
   107  	}()
   108  
   109  	appErr := w.app.BulkExport(wr, outPath, opts)
   110  	if err := wr.Close(); err != nil {
   111  		mlog.Warn("Worker: error closing writer")
   112  	}
   113  	if appErr != nil {
   114  		w.setJobError(job, appErr)
   115  		return
   116  	}
   117  
   118  	if appErr := <-errCh; appErr != nil {
   119  		w.setJobError(job, appErr)
   120  		return
   121  	}
   122  
   123  	mlog.Info("Worker: Job is complete", mlog.String("worker", w.name), mlog.String("job_id", job.Id))
   124  	w.setJobSuccess(job)
   125  }
   126  
   127  func (w *ExportProcessWorker) setJobSuccess(job *model.Job) {
   128  	if err := w.app.Srv().Jobs.SetJobSuccess(job); err != nil {
   129  		mlog.Error("Worker: Failed to set success for job", mlog.String("worker", w.name), mlog.String("job_id", job.Id), mlog.String("error", err.Error()))
   130  		w.setJobError(job, err)
   131  	}
   132  }
   133  
   134  func (w *ExportProcessWorker) setJobError(job *model.Job, appError *model.AppError) {
   135  	if err := w.app.Srv().Jobs.SetJobError(job, appError); err != nil {
   136  		mlog.Error("Worker: Failed to set job error", mlog.String("worker", w.name), mlog.String("job_id", job.Id), mlog.String("error", err.Error()))
   137  	}
   138  }