Implement app update orchestration (T-402)
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
package windows
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
const exitPollInterval = 250 * time.Millisecond
|
||||
|
||||
type exitWaitClock interface {
|
||||
Now() time.Time
|
||||
Wait(context.Context, time.Duration) error
|
||||
}
|
||||
|
||||
type systemExitWaitClock struct{}
|
||||
|
||||
func (systemExitWaitClock) Now() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
func (systemExitWaitClock) Wait(ctx context.Context, duration time.Duration) error {
|
||||
timer := time.NewTimer(duration)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-timer.C:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitForExit(ctx context.Context, timeout time.Duration, running func() (bool, error), clock exitWaitClock) error {
|
||||
if ctx == nil {
|
||||
return fmt.Errorf("wait context is required")
|
||||
}
|
||||
if timeout <= 0 {
|
||||
return fmt.Errorf("exit timeout must be positive")
|
||||
}
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
deadline := clock.Now().Add(timeout)
|
||||
for {
|
||||
isRunning, err := running()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isRunning {
|
||||
return nil
|
||||
}
|
||||
remaining := deadline.Sub(clock.Now())
|
||||
if remaining <= 0 {
|
||||
return context.DeadlineExceeded
|
||||
}
|
||||
interval := exitPollInterval
|
||||
if remaining < interval {
|
||||
interval = remaining
|
||||
}
|
||||
if err := clock.Wait(ctx, interval); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user