Refactor resume worker to handle unexpected wall-clock changes and improve SPN auto-resume logic
This commit is contained in:
@@ -133,50 +133,65 @@ func (c *Control) stopResumeWorker() {
|
|||||||
// startResumeWorker starts a worker that will resume normal operation after the specified duration.
|
// startResumeWorker starts a worker that will resume normal operation after the specified duration.
|
||||||
// No thread safety, caller must hold c.locker.
|
// No thread safety, caller must hold c.locker.
|
||||||
func (c *Control) startResumeWorker(duration time.Duration) {
|
func (c *Control) startResumeWorker(duration time.Duration) {
|
||||||
c.pauseInfo.TillTime = time.Now().Add(duration)
|
deadline := time.Now().Add(duration)
|
||||||
|
c.pauseInfo.TillTime = deadline
|
||||||
|
|
||||||
resumerWorkerFunc := func(wc *mgr.WorkerCtx) error {
|
resumerWorkerFunc := func(wc *mgr.WorkerCtx) error {
|
||||||
wc.Info(fmt.Sprintf("Scheduling resume in %v", duration))
|
wc.Info(fmt.Sprintf("Scheduling resume in %v", duration))
|
||||||
|
|
||||||
// Subscribe to config changes to detect SPN enable.
|
// Subscribe to config changes to detect SPN enable.
|
||||||
cfgChangeEvt := c.instance.Config().EventConfigChange.Subscribe("control: spn enable check", 10)
|
cfgChangeEvt := c.instance.Config().EventConfigChange.Subscribe("control: spn enable check", 10)
|
||||||
// Make sure to cancel subscription when worker stops.
|
|
||||||
defer cfgChangeEvt.Cancel()
|
defer cfgChangeEvt.Cancel()
|
||||||
|
|
||||||
for {
|
// Timer for the deadline.
|
||||||
|
timer := time.NewTimer(time.Until(deadline))
|
||||||
|
defer timer.Stop()
|
||||||
|
// Periodically check resume time to handle unexpected wall-clock changes.
|
||||||
|
ticker := time.NewTicker(15 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
// Wait until duration elapses or SPN is enabled by user.
|
||||||
|
needToAutoResume := false
|
||||||
|
for !needToAutoResume {
|
||||||
select {
|
select {
|
||||||
case <-wc.Ctx().Done():
|
case <-wc.Ctx().Done():
|
||||||
return nil
|
return nil
|
||||||
case <-cfgChangeEvt.Events():
|
case <-cfgChangeEvt.Events():
|
||||||
spnEnabled := config.GetAsBool("spn/enable", false)
|
spnEnabled := config.GetAsBool("spn/enable", false)
|
||||||
if spnEnabled() {
|
if spnEnabled() {
|
||||||
wc.Info("SPN enabled by user, resuming...")
|
wc.Info("SPN enabled by user. Auto-resume initiated.")
|
||||||
return c.resume()
|
needToAutoResume = true
|
||||||
}
|
}
|
||||||
case <-time.After(duration):
|
case <-ticker.C:
|
||||||
wc.Info("Resuming...")
|
if time.Now().After(deadline) {
|
||||||
|
needToAutoResume = true
|
||||||
err := c.resume()
|
|
||||||
if err == nil {
|
|
||||||
n := ¬ifications.Notification{
|
|
||||||
EventID: "control:resumed",
|
|
||||||
Type: notifications.Info,
|
|
||||||
Title: "Resumed",
|
|
||||||
Message: "Automatically resumed from pause state",
|
|
||||||
ShowOnSystem: true,
|
|
||||||
Expires: time.Now().Add(15 * time.Second).Unix(),
|
|
||||||
AvailableActions: []*notifications.Action{
|
|
||||||
{
|
|
||||||
ID: "ack",
|
|
||||||
Text: "OK",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
notifications.Notify(n)
|
|
||||||
}
|
}
|
||||||
return err
|
case <-timer.C:
|
||||||
|
needToAutoResume = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Time to resume
|
||||||
|
wc.Info("Resuming...")
|
||||||
|
err := c.resume()
|
||||||
|
if err == nil {
|
||||||
|
n := ¬ifications.Notification{
|
||||||
|
EventID: "control:resumed",
|
||||||
|
Type: notifications.Info,
|
||||||
|
Title: "Resumed",
|
||||||
|
Message: "Automatically resumed from pause state",
|
||||||
|
ShowOnSystem: true,
|
||||||
|
Expires: time.Now().Add(15 * time.Second).Unix(),
|
||||||
|
AvailableActions: []*notifications.Action{
|
||||||
|
{
|
||||||
|
ID: "ack",
|
||||||
|
Text: "OK",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
notifications.Notify(n)
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.resumeWorker = c.mgr.NewWorkerMgr("resumer", resumerWorkerFunc, nil)
|
c.resumeWorker = c.mgr.NewWorkerMgr("resumer", resumerWorkerFunc, nil)
|
||||||
|
|||||||
Reference in New Issue
Block a user