github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/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/rclone/rclone/fs" 11 "github.com/rclone/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 }