mirror of https://github.com/k3s-io/k3s
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
1.4 KiB
74 lines
1.4 KiB
package cancel
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"sync"
|
|
)
|
|
|
|
// Canceler tracks a cancelable operation
|
|
type Canceler struct {
|
|
reqChCancel map[*http.Request]chan struct{}
|
|
lock sync.Mutex
|
|
}
|
|
|
|
// NewCanceler returns a new Canceler struct
|
|
func NewCanceler() *Canceler {
|
|
c := Canceler{}
|
|
|
|
c.lock.Lock()
|
|
c.reqChCancel = make(map[*http.Request]chan struct{})
|
|
c.lock.Unlock()
|
|
|
|
return &c
|
|
}
|
|
|
|
// Cancelable indicates whether there are operations that support cancelation
|
|
func (c *Canceler) Cancelable() bool {
|
|
c.lock.Lock()
|
|
length := len(c.reqChCancel)
|
|
c.lock.Unlock()
|
|
|
|
return length > 0
|
|
}
|
|
|
|
// Cancel will attempt to cancel all ongoing operations
|
|
func (c *Canceler) Cancel() error {
|
|
if !c.Cancelable() {
|
|
return fmt.Errorf("This operation can't be canceled at this time")
|
|
}
|
|
|
|
c.lock.Lock()
|
|
for req, ch := range c.reqChCancel {
|
|
close(ch)
|
|
delete(c.reqChCancel, req)
|
|
}
|
|
c.lock.Unlock()
|
|
|
|
return nil
|
|
}
|
|
|
|
// CancelableDownload performs an http request and allows for it to be canceled at any time
|
|
func CancelableDownload(c *Canceler, client *http.Client, req *http.Request) (*http.Response, chan bool, error) {
|
|
chDone := make(chan bool)
|
|
chCancel := make(chan struct{})
|
|
if c != nil {
|
|
c.lock.Lock()
|
|
c.reqChCancel[req] = chCancel
|
|
c.lock.Unlock()
|
|
}
|
|
req.Cancel = chCancel
|
|
|
|
go func() {
|
|
<-chDone
|
|
if c != nil {
|
|
c.lock.Lock()
|
|
delete(c.reqChCancel, req)
|
|
c.lock.Unlock()
|
|
}
|
|
}()
|
|
|
|
resp, err := client.Do(req)
|
|
return resp, chDone, err
|
|
}
|