github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/worker/moves/workers.go (about)

     1  package moves
     2  
     3  import (
     4  	"runtime"
     5  	"time"
     6  
     7  	"github.com/cozy/cozy-stack/model/instance"
     8  	"github.com/cozy/cozy-stack/model/instance/lifecycle"
     9  	"github.com/cozy/cozy-stack/model/job"
    10  	"github.com/cozy/cozy-stack/model/move"
    11  )
    12  
    13  func init() {
    14  	job.AddWorker(&job.WorkerConfig{
    15  		WorkerType:   "export",
    16  		Concurrency:  runtime.NumCPU(),
    17  		MaxExecCount: 1,
    18  		Timeout:      1 * time.Hour,
    19  		WorkerFunc:   ExportWorker,
    20  	})
    21  
    22  	job.AddWorker(&job.WorkerConfig{
    23  		WorkerType:   "import",
    24  		Concurrency:  runtime.NumCPU(),
    25  		MaxExecCount: 1,
    26  		Timeout:      3 * time.Hour,
    27  		WorkerFunc:   ImportWorker,
    28  	})
    29  }
    30  
    31  // ExportWorker is the worker responsible for creating an export of the
    32  // instance.
    33  func ExportWorker(c *job.TaskContext) error {
    34  	var opts move.ExportOptions
    35  	if err := c.UnmarshalMessage(&opts); err != nil {
    36  		return err
    37  	}
    38  
    39  	if opts.ContextualDomain != "" {
    40  		c.Instance = c.Instance.WithContextualDomain(opts.ContextualDomain)
    41  	}
    42  
    43  	archiver := move.SystemArchiver()
    44  
    45  	exportDoc, err := move.CreateExport(c.Instance, opts, archiver)
    46  	if err != nil {
    47  		c.Instance.Logger().WithNamespace("move").
    48  			Warnf("Export failed: %s", err)
    49  		if opts.MoveTo != nil {
    50  			move.Abort(c.Instance, opts.MoveTo.URL, opts.MoveTo.Token)
    51  		}
    52  		if !opts.AdminReq {
    53  			_ = move.SendExportFailureMail(c.Instance)
    54  		}
    55  		return err
    56  	}
    57  
    58  	if opts.AdminReq {
    59  		exportDoc.NotifyRealtime()
    60  		return nil
    61  	}
    62  	if opts.MoveTo != nil {
    63  		return exportDoc.NotifyTarget(c.Instance, opts.MoveTo, opts.TokenSource, opts.IgnoreVault)
    64  	}
    65  	return exportDoc.SendExportMail(c.Instance)
    66  }
    67  
    68  // ImportWorker is the worker responsible for inserting the data from an export
    69  // inside an instance.
    70  func ImportWorker(c *job.TaskContext) error {
    71  	var opts move.ImportOptions
    72  	if err := c.UnmarshalMessage(&opts); err != nil {
    73  		return err
    74  	}
    75  
    76  	if err := lifecycle.Block(c.Instance, instance.BlockedImporting.Code); err != nil {
    77  		return err
    78  	}
    79  
    80  	inError, err := move.Import(c.Instance, opts)
    81  
    82  	if erru := lifecycle.Unblock(c.Instance); erru != nil {
    83  		// Try again
    84  		time.Sleep(10 * time.Second)
    85  		inst, errg := instance.Get(c.Instance.Domain)
    86  		if errg == nil {
    87  			erru = lifecycle.Unblock(inst)
    88  		}
    89  		if err == nil {
    90  			err = erru
    91  		}
    92  	}
    93  
    94  	status := move.StatusImportSuccess
    95  	if err != nil {
    96  		status = move.StatusImportFailure
    97  		if opts.MoveFrom != nil {
    98  			status = move.StatusMoveFailure
    99  		}
   100  		c.Instance.Logger().WithNamespace("move").
   101  			Warnf("Import failed: %s", err)
   102  	}
   103  
   104  	if opts.MoveFrom != nil {
   105  		if err == nil {
   106  			status = move.StatusMoveSuccess
   107  			move.CallFinalize(c.Instance, opts.MoveFrom.URL, opts.MoveFrom.Token, opts.Vault)
   108  		} else {
   109  			move.Abort(c.Instance, opts.MoveFrom.URL, opts.MoveFrom.Token)
   110  		}
   111  	}
   112  
   113  	_ = move.SendImportDoneMail(c.Instance, status, inError)
   114  	if err != nil {
   115  		return err
   116  	}
   117  
   118  	if opts.MoveFrom == nil {
   119  		return nil
   120  	}
   121  	return move.NotifySharings(c.Instance)
   122  }