Manager: consult the sleep schedule on worker sign-on
If there is no status change queued for the Worker, the sleep schedule should determine its initial status.
This commit is contained in:
parent
bc725ea7dc
commit
bfd6746f78
@ -208,6 +208,7 @@ var _ TimeService = (clock.Clock)(nil)
|
|||||||
type WorkerSleepScheduler interface {
|
type WorkerSleepScheduler interface {
|
||||||
FetchSchedule(ctx context.Context, workerUUID string) (*persistence.SleepSchedule, error)
|
FetchSchedule(ctx context.Context, workerUUID string) (*persistence.SleepSchedule, error)
|
||||||
SetSchedule(ctx context.Context, workerUUID string, schedule *persistence.SleepSchedule) error
|
SetSchedule(ctx context.Context, workerUUID string, schedule *persistence.SleepSchedule) error
|
||||||
|
WorkerStatus(ctx context.Context, workerUUID string) (api.WorkerStatus, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ WorkerSleepScheduler = (*sleep_scheduler.SleepScheduler)(nil)
|
var _ WorkerSleepScheduler = (*sleep_scheduler.SleepScheduler)(nil)
|
||||||
|
@ -1139,3 +1139,18 @@ func (mr *MockWorkerSleepSchedulerMockRecorder) SetSchedule(arg0, arg1, arg2 int
|
|||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSchedule", reflect.TypeOf((*MockWorkerSleepScheduler)(nil).SetSchedule), arg0, arg1, arg2)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSchedule", reflect.TypeOf((*MockWorkerSleepScheduler)(nil).SetSchedule), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WorkerStatus mocks base method.
|
||||||
|
func (m *MockWorkerSleepScheduler) WorkerStatus(arg0 context.Context, arg1 string) (api.WorkerStatus, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "WorkerStatus", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(api.WorkerStatus)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// WorkerStatus indicates an expected call of WorkerStatus.
|
||||||
|
func (mr *MockWorkerSleepSchedulerMockRecorder) WorkerStatus(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WorkerStatus", reflect.TypeOf((*MockWorkerSleepScheduler)(nil).WorkerStatus), arg0, arg1)
|
||||||
|
}
|
||||||
|
@ -79,27 +79,38 @@ func (f *Flamenco) SignOn(e echo.Context) error {
|
|||||||
return sendAPIError(e, http.StatusBadRequest, "invalid format")
|
return sendAPIError(e, http.StatusBadRequest, "invalid format")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info().Msg("worker signing on")
|
|
||||||
w, prevStatus, err := f.workerUpdateAfterSignOn(e, req)
|
w, prevStatus, err := f.workerUpdateAfterSignOn(e, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sendAPIError(e, http.StatusInternalServerError, "error storing worker in database")
|
return sendAPIError(e, http.StatusInternalServerError, "error storing worker in database")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Broadcast the status change.
|
// Broadcast the status change to 'starting'.
|
||||||
update := webupdates.NewWorkerUpdate(w)
|
update := webupdates.NewWorkerUpdate(w)
|
||||||
if prevStatus != "" {
|
if prevStatus != "" {
|
||||||
update.PreviousStatus = &prevStatus
|
update.PreviousStatus = &prevStatus
|
||||||
}
|
}
|
||||||
f.broadcaster.BroadcastWorkerUpdate(update)
|
f.broadcaster.BroadcastWorkerUpdate(update)
|
||||||
|
|
||||||
resp := api.WorkerStateChange{}
|
// Get the status the Worker should go to after starting up.
|
||||||
if w.StatusRequested != "" {
|
ctx := e.Request().Context()
|
||||||
resp.StatusRequested = w.StatusRequested
|
initialStatus, err := f.workerInitialStatus(ctx, w)
|
||||||
} else {
|
if err != nil {
|
||||||
resp.StatusRequested = api.WorkerStatusAwake
|
return sendAPIError(e, http.StatusInternalServerError, "error figuring out your initial status: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.JSON(http.StatusOK, resp)
|
logger.Info().Str("initialStatus", string(initialStatus)).Msg("worker signing on")
|
||||||
|
|
||||||
|
return e.JSON(http.StatusOK, api.WorkerStateChange{
|
||||||
|
StatusRequested: initialStatus,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// workerInitialStatus returns the status the worker should go to after starting up.
|
||||||
|
func (f *Flamenco) workerInitialStatus(ctx context.Context, w *persistence.Worker) (api.WorkerStatus, error) {
|
||||||
|
if w.StatusRequested != "" {
|
||||||
|
return w.StatusRequested, nil
|
||||||
|
}
|
||||||
|
return f.sleepScheduler.WorkerStatus(ctx, w.UUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flamenco) workerUpdateAfterSignOn(e echo.Context, update api.SignOnJSONBody) (*persistence.Worker, api.WorkerStatus, error) {
|
func (f *Flamenco) workerUpdateAfterSignOn(e echo.Context, update api.SignOnJSONBody) (*persistence.Worker, api.WorkerStatus, error) {
|
||||||
|
@ -168,6 +168,9 @@ func TestWorkerSignOn(t *testing.T) {
|
|||||||
worker.Status = api.WorkerStatusOffline
|
worker.Status = api.WorkerStatusOffline
|
||||||
prevStatus := worker.Status
|
prevStatus := worker.Status
|
||||||
|
|
||||||
|
mf.sleepScheduler.EXPECT().WorkerStatus(gomock.Any(), worker.UUID).
|
||||||
|
Return(api.WorkerStatusAsleep, nil)
|
||||||
|
|
||||||
mf.broadcaster.EXPECT().BroadcastWorkerUpdate(api.SocketIOWorkerUpdate{
|
mf.broadcaster.EXPECT().BroadcastWorkerUpdate(api.SocketIOWorkerUpdate{
|
||||||
Id: worker.UUID,
|
Id: worker.UUID,
|
||||||
Name: "Lazy Boi",
|
Name: "Lazy Boi",
|
||||||
@ -190,7 +193,7 @@ func TestWorkerSignOn(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assertResponseJSON(t, echo, http.StatusOK, api.WorkerStateChange{
|
assertResponseJSON(t, echo, http.StatusOK, api.WorkerStateChange{
|
||||||
StatusRequested: api.WorkerStatusAwake,
|
StatusRequested: api.WorkerStatusAsleep,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,11 @@ import (
|
|||||||
|
|
||||||
// scheduledWorkerStatus returns the expected worker status at the given date/time.
|
// scheduledWorkerStatus returns the expected worker status at the given date/time.
|
||||||
func scheduledWorkerStatus(now time.Time, sched *persistence.SleepSchedule) api.WorkerStatus {
|
func scheduledWorkerStatus(now time.Time, sched *persistence.SleepSchedule) api.WorkerStatus {
|
||||||
|
if sched == nil {
|
||||||
|
// If there is no schedule at all, the worker should be awake.
|
||||||
|
return api.WorkerStatusAwake
|
||||||
|
}
|
||||||
|
|
||||||
tod := persistence.MakeTimeOfDay(now)
|
tod := persistence.MakeTimeOfDay(now)
|
||||||
|
|
||||||
if !sched.IsActive {
|
if !sched.IsActive {
|
||||||
|
@ -52,6 +52,9 @@ func TestScheduledWorkerStatus(t *testing.T) {
|
|||||||
var sched persistence.SleepSchedule
|
var sched persistence.SleepSchedule
|
||||||
empty := persistence.EmptyTimeOfDay()
|
empty := persistence.EmptyTimeOfDay()
|
||||||
|
|
||||||
|
// No schedule means 'awake'.
|
||||||
|
assert.Equal(t, api.WorkerStatusAwake, scheduledWorkerStatus(mocks.todayAt(11, 16), nil))
|
||||||
|
|
||||||
// Below, S, N, and E respectively mean Start, Now, and End times.
|
// Below, S, N, and E respectively mean Start, Now, and End times.
|
||||||
// Their order shows their relation to "Now". Lower-case letters mean "no value".
|
// Their order shows their relation to "Now". Lower-case letters mean "no value".
|
||||||
// Note that N can never be before 's' or after 'e'.
|
// Note that N can never be before 's' or after 'e'.
|
||||||
|
@ -75,6 +75,16 @@ func (ss *SleepScheduler) SetSchedule(ctx context.Context, workerUUID string, sc
|
|||||||
return ss.ApplySleepSchedule(ctx, schedule)
|
return ss.ApplySleepSchedule(ctx, schedule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WorkerStatus returns the status the worker should be in right now, according to its schedule.
|
||||||
|
// If the worker has no schedule active, returns 'awake'.
|
||||||
|
func (ss *SleepScheduler) WorkerStatus(ctx context.Context, workerUUID string) (api.WorkerStatus, error) {
|
||||||
|
schedule, err := ss.persist.FetchWorkerSleepSchedule(ctx, workerUUID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return ss.scheduledWorkerStatus(schedule), nil
|
||||||
|
}
|
||||||
|
|
||||||
// scheduledWorkerStatus returns the expected worker status for the current date/time.
|
// scheduledWorkerStatus returns the expected worker status for the current date/time.
|
||||||
func (ss *SleepScheduler) scheduledWorkerStatus(sched *persistence.SleepSchedule) api.WorkerStatus {
|
func (ss *SleepScheduler) scheduledWorkerStatus(sched *persistence.SleepSchedule) api.WorkerStatus {
|
||||||
now := ss.clock.Now()
|
now := ss.clock.Now()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user