Add deadline.md links

- Update example using assert
- Fix typo on circuit-breaker.md
This commit is contained in:
Fahim Bagar 2020-08-01 06:44:26 +07:00
parent 450bb1c95d
commit 9001fb9e96
3 changed files with 104 additions and 5 deletions

View File

@ -12,7 +12,7 @@ document.
## Implementation ## Implementation
Below is the implementation of a very simple circuit breaker to illustrate the purpose Below is the implementation of a very simple circuit breaker to illustrate the purpose
of the circuit breaker design pattern ,Only considering Open/Closed of the circuit breaker design pattern, only considering Open/Closed
### Operation Counter ### Operation Counter

93
stability/deadline.md Normal file
View File

@ -0,0 +1,93 @@
# Deadline Pattern
Package deadline implements the deadline (also known as "timeout") resiliency pattern for Go.
## Implementation
Below is the implementation of a very simple deadline to illustrate the purpose
of the deadline design pattern.
### Deadline Constructor
`Deadline` is a simple struct that implements timeout duration checking for maximum execution time.
```go
package deadline
import (
"errors"
"time"
)
// ErrTimedOut is the error returned from Run when the deadline expires.
var ErrTimedOut = errors.New("timed out waiting for function to finish")
// Deadline implements the deadline/timeout resiliency pattern.
type Deadline struct {
timeout time.Duration
}
// New constructs a new Deadline with the given timeout.
func New(timeout time.Duration) *Deadline {
return &Deadline{
timeout: timeout,
}
}
```
### Deadline Implementation
`Run` runs the given function, passing it a stopper channel. If the deadline passes before 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 keep running after the deadline passes. If the function finishes before the deadline, then the return value of the function is returned from `Run`.
**Note:** Deadline can be replaced by Context, check the [Related Content](#related-contents).
```go
func (d *Deadline) Run(work func(<-chan struct{}) error) error {
result := make(chan error)
stopper := make(chan struct{})
go func() {
value := work(stopper)
select {
case result <- value:
case <-stopper:
}
}()
select {
case ret := <-result:
return ret
case <-time.After(d.timeout):
close(stopper)
return ErrTimedOut
}
}
```
### Deadline Usage
```go
func ExampleDeadline() {
dl := New(1 * time.Second)
err := dl.Run(func(stopper <-chan struct{}) error {
// do something possibly slow
// check stopper function and give up if timed out
return nil
})
switch err {
case ErrTimedOut:
// execution took too long, oops
default:
// some other error
}
}
```
# Related Contents
- [Deadline in Golang using Context](https://blog.golang.org/context)
- [Example using Context](https://golang.org/src/context/example_test.go)

View File

@ -6,6 +6,12 @@ import (
"time" "time"
) )
func assertEqual(t *testing.T, a interface{}, b interface{}) {
if a != b {
t.Fatalf("%s != %s", a, b)
}
}
func takesFiveMillis(stopper <-chan struct{}) error { func takesFiveMillis(stopper <-chan struct{}) error {
time.Sleep(5 * time.Millisecond) time.Sleep(5 * time.Millisecond)
return nil return nil
@ -27,12 +33,12 @@ func TestDeadline(t *testing.T) {
t.Error(err) t.Error(err)
} }
if err := dl.Run(takesTwentyMillis); err != ErrTimedOut { if err := dl.Run(takesTwentyMillis); err != nil {
t.Error(err) assertEqual(t, err, ErrTimedOut)
} }
if err := dl.Run(returnsError); err.Error() != "foo" { if err := dl.Run(returnsError); err != nil {
t.Error(err) assertEqual(t, err.Error(), "foo")
} }
done := make(chan struct{}) done := make(chan struct{})