github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/backend/seafile/renew.go (about) 1 package seafile 2 3 import ( 4 "sync" 5 "time" 6 7 "github.com/rclone/rclone/fs" 8 ) 9 10 // Renew allows tokens to be renewed on expiry. 11 type Renew struct { 12 ts *time.Ticker // timer indicating when it's time to renew the token 13 run func() error // the callback to do the renewal 14 done chan interface{} // channel to end the go routine 15 shutdown *sync.Once 16 } 17 18 // NewRenew creates a new Renew struct and starts a background process 19 // which renews the token whenever it expires. It uses the run() call 20 // to do the renewal. 21 func NewRenew(every time.Duration, run func() error) *Renew { 22 r := &Renew{ 23 ts: time.NewTicker(every), 24 run: run, 25 done: make(chan interface{}), 26 shutdown: &sync.Once{}, 27 } 28 go r.renewOnExpiry() 29 return r 30 } 31 32 func (r *Renew) renewOnExpiry() { 33 for { 34 select { 35 case <-r.ts.C: 36 err := r.run() 37 if err != nil { 38 fs.Errorf(nil, "error while refreshing decryption token: %s", err) 39 } 40 41 case <-r.done: 42 return 43 } 44 } 45 } 46 47 // Shutdown stops the ticker and no more renewal will take place. 48 func (r *Renew) Shutdown() { 49 // closing a channel can only be done once 50 r.shutdown.Do(func() { 51 r.ts.Stop() 52 close(r.done) 53 }) 54 }