Sybren A. Stüvel 1355ec5e1d Worker: Change how the worker shuts down
Instead of sending the current process an interrupt signal, use a dedicated
channel to signal the wish to shut down. The main function responds to that
channel closing by performing the shutdown.

This solves an issue where the Worker would not cleanly shut down on
Windows when `offline` state was requested by the Manager.
2022-08-12 11:15:19 -07:00

83 lines
1.8 KiB
Go

package worker
// SPDX-License-Identifier: GPL-3.0-or-later
import (
"context"
"sync"
"github.com/rs/zerolog/log"
"git.blender.org/flamenco/pkg/api"
)
// Worker performs regular Flamenco Worker operations.
type Worker struct {
doneChan chan struct{}
doneWg *sync.WaitGroup
// Will be closed by the Worker when it wants to shut down. See Worker.WaitForShutdown().
shutdown chan struct{}
client FlamencoClient
state api.WorkerStatus
stateStarters map[api.WorkerStatus]StateStarter // gotoStateXXX functions
stateMutex *sync.Mutex
taskRunner TaskRunner
}
type StateStarter func(context.Context)
type TaskRunner interface {
Run(ctx context.Context, task api.AssignedTask) error
}
// NewWorker constructs and returns a new Worker.
func NewWorker(
flamenco FlamencoClient,
taskRunner TaskRunner,
) *Worker {
worker := &Worker{
doneChan: make(chan struct{}),
doneWg: new(sync.WaitGroup),
shutdown: make(chan struct{}),
client: flamenco,
state: api.WorkerStatusStarting,
stateStarters: make(map[api.WorkerStatus]StateStarter),
stateMutex: new(sync.Mutex),
taskRunner: taskRunner,
}
worker.setupStateMachine()
return worker
}
// Start starts the worker by sending it to the given state.
func (w *Worker) Start(ctx context.Context, state api.WorkerStatus) {
w.changeState(ctx, state)
}
// Close gracefully shuts down the Worker.
func (w *Worker) Close() {
log.Debug().Msg("worker gracefully shutting down")
close(w.doneChan)
w.doneWg.Wait()
}
// WaitForShutdown waits until Flamenco wants to shut down the application.
// Returns `true` when the Worker has signalled it wants to shut down.
// Returns `false` when the shutdown was caused by the context closing.
func (w *Worker) WaitForShutdown(ctx context.Context) bool {
select {
case <-ctx.Done():
return false
case <-w.shutdown:
return true
}
}