go-pattern-examples/resiliency/03_deadline/deadline.go

66 lines
1.7 KiB
Go
Raw Permalink Normal View History

2020-06-05 07:57:11 +03:00
/*
* @Description: https://github.com/crazybber
* @Author: Edward
* @Date: 2020-06-05 12:43:39
* @Last Modified by: Edward
2020-06-05 12:36:30 +03:00
* @Last Modified time: 2020-06-05 17:34:37
2020-06-05 07:57:11 +03:00
*/
2020-06-05 12:36:30 +03:00
// Package deadline implements deadline (also known as "timeout") resiliency pattern for Go.
2020-05-03 05:53:23 +03:00
package deadline
import (
"errors"
"time"
)
2020-06-05 12:36:30 +03:00
// ErrTimedOut is the error returned from Run when the Worker expires.
2020-05-03 05:53:23 +03:00
var ErrTimedOut = errors.New("timed out waiting for function to finish")
2020-06-05 12:36:30 +03:00
// Worker implements the Deadline/timeout resiliency pattern.
// worker do the target job
type Worker struct {
2020-05-03 05:53:23 +03:00
timeout time.Duration
2020-06-05 07:57:11 +03:00
action string
2020-05-03 05:53:23 +03:00
}
2020-06-05 12:36:30 +03:00
// New create a new Worker with the given timeout.and tile
func New(timeout time.Duration, someActionTitle string) *Worker {
return &Worker{
2020-05-03 05:53:23 +03:00
timeout: timeout,
2020-06-05 12:36:30 +03:00
action: someActionTitle,
2020-05-03 05:53:23 +03:00
}
}
2020-06-05 12:36:30 +03:00
// Run runs the given function, passing it a stopper channel. If the Worker passes before
2020-05-03 05:53:23 +03:00
// the function finishes executing, Run returns ErrTimeOut to the caller and closes the stopper
// channel so that the work function can attempt to exit gracefully. It does not (and cannot)
// simply kill the running function, so if it doesn't respect the stopper channel then it may
2020-06-05 12:36:30 +03:00
// keep running after the Worker passes. If the function finishes before the Worker, then
2020-05-03 05:53:23 +03:00
// the return value of the function is returned from Run.
2020-06-05 12:36:30 +03:00
func (d *Worker) Run(work func(stopperSignal chan error) error) error {
2020-06-05 07:57:11 +03:00
2020-06-05 12:36:30 +03:00
result := make(chan error)
//we can stop the work in advance
stopper := make(chan error, 1)
2020-05-03 05:53:23 +03:00
go func() {
value := work(stopper)
select {
case result <- value:
2020-06-05 12:36:30 +03:00
case stopError := <-stopper:
result <- stopError
2020-05-03 05:53:23 +03:00
}
}()
2020-06-05 07:57:11 +03:00
//handle result
2020-05-03 05:53:23 +03:00
select {
case ret := <-result:
return ret
case <-time.After(d.timeout):
close(stopper)
return ErrTimedOut
}
}