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