github.com/artpar/rclone@v1.67.3/backend/seafile/renew.go (about)

     1  package seafile
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	"github.com/artpar/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  }