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

     1  package seafile
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/url"
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/artpar/rclone/fs"
    11  	"github.com/artpar/rclone/lib/pacer"
    12  )
    13  
    14  const (
    15  	minSleep      = 100 * time.Millisecond
    16  	maxSleep      = 10 * time.Second
    17  	decayConstant = 2 // bigger for slower decay, exponential
    18  )
    19  
    20  // Use only one pacer per server URL
    21  var (
    22  	pacers     map[string]*fs.Pacer
    23  	pacerMutex sync.Mutex
    24  )
    25  
    26  func init() {
    27  	pacers = make(map[string]*fs.Pacer, 0)
    28  }
    29  
    30  // getPacer returns the unique pacer for that remote URL
    31  func getPacer(ctx context.Context, remote string) *fs.Pacer {
    32  	pacerMutex.Lock()
    33  	defer pacerMutex.Unlock()
    34  
    35  	remote = parseRemote(remote)
    36  	if existing, found := pacers[remote]; found {
    37  		return existing
    38  	}
    39  
    40  	pacers[remote] = fs.NewPacer(
    41  		ctx,
    42  		pacer.NewDefault(
    43  			pacer.MinSleep(minSleep),
    44  			pacer.MaxSleep(maxSleep),
    45  			pacer.DecayConstant(decayConstant),
    46  		),
    47  	)
    48  	return pacers[remote]
    49  }
    50  
    51  // parseRemote formats a remote url into "hostname:port"
    52  func parseRemote(remote string) string {
    53  	remoteURL, err := url.Parse(remote)
    54  	if err != nil {
    55  		// Return a default value in the very unlikely event we're not going to parse remote
    56  		fs.Infof(nil, "Cannot parse remote %s", remote)
    57  		return "default"
    58  	}
    59  	host := remoteURL.Hostname()
    60  	port := remoteURL.Port()
    61  	if port == "" {
    62  		if remoteURL.Scheme == "https" {
    63  			port = "443"
    64  		} else {
    65  			port = "80"
    66  		}
    67  	}
    68  	return fmt.Sprintf("%s:%s", host, port)
    69  }