File: deadline.go

package info (click to toggle)
golang-gopkg-eapache-go-resiliency.v1 1.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 180 kB
  • sloc: makefile: 2
file content (47 lines) | stat: -rw-r--r-- 1,425 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Package deadline implements the deadline (also known as "timeout") resiliency pattern for 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,
	}
}

// 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)
// kill the running function's goroutine, so if the function 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.
func (d *Deadline) Run(work func(<-chan struct{}) error) error {
	result := make(chan error, 1)
	stopper := make(chan struct{})

	go func() {
		result <- work(stopper)
	}()

	timer := time.NewTimer(d.timeout)
	select {
	case ret := <-result:
		timer.Stop()
		return ret
	case <-timer.C:
		close(stopper)
		return ErrTimedOut
	}
}