diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/transport/controller.go | 26 | ||||
| -rw-r--r-- | internal/transport/transport.go | 21 | 
2 files changed, 37 insertions, 10 deletions
diff --git a/internal/transport/controller.go b/internal/transport/controller.go index 5a72871d8..4db8ee00e 100644 --- a/internal/transport/controller.go +++ b/internal/transport/controller.go @@ -51,7 +51,8 @@ type controller struct {  	fedDB     federatingdb.DB  	clock     pub.Clock  	client    pub.HttpClient -	cache     cache.Cache[string, *transport] +	trspCache cache.Cache[string, *transport] +	badHosts  cache.Cache[string, struct{}]  	userAgent string  } @@ -66,13 +67,20 @@ func NewController(db db.DB, federatingDB federatingdb.DB, clock pub.Clock, clie  		fedDB:     federatingDB,  		clock:     clock,  		client:    client, -		cache:     cache.New[string, *transport](), +		trspCache: cache.New[string, *transport](), +		badHosts:  cache.New[string, struct{}](),  		userAgent: fmt.Sprintf("%s; %s (gofed/activity gotosocial-%s)", applicationName, host, version),  	} -	// Transport cache has TTL=1hr freq=1m -	c.cache.SetTTL(time.Hour, false) -	if !c.cache.Start(time.Minute) { +	// Transport cache has TTL=1hr freq=1min +	c.trspCache.SetTTL(time.Hour, false) +	if !c.trspCache.Start(time.Minute) { +		log.Panic("failed to start transport controller cache") +	} + +	// Bad hosts cache has TTL=15min freq=1min +	c.badHosts.SetTTL(15*time.Minute, false) +	if !c.badHosts.Start(time.Minute) {  		log.Panic("failed to start transport controller cache")  	} @@ -89,7 +97,7 @@ func (c *controller) NewTransport(pubKeyID string, privkey *rsa.PrivateKey) (Tra  	pubStr := privkeyToPublicStr(privkey)  	// First check for cached transport -	transp, ok := c.cache.Get(pubStr) +	transp, ok := c.trspCache.Get(pubStr)  	if ok {  		return transp, nil  	} @@ -102,13 +110,13 @@ func (c *controller) NewTransport(pubKeyID string, privkey *rsa.PrivateKey) (Tra  	}  	// Cache this transport under pubkey -	if !c.cache.Put(pubStr, transp) { +	if !c.trspCache.Put(pubStr, transp) {  		var cached *transport -		cached, ok = c.cache.Get(pubStr) +		cached, ok = c.trspCache.Get(pubStr)  		if !ok {  			// Some ridiculous race cond. -			c.cache.Set(pubStr, transp) +			c.trspCache.Set(pubStr, transp)  		} else {  			// Use already cached  			transp = cached diff --git a/internal/transport/transport.go b/internal/transport/transport.go index 5af8b738e..94a0cc8ef 100644 --- a/internal/transport/transport.go +++ b/internal/transport/transport.go @@ -88,7 +88,23 @@ func (t *transport) POST(r *http.Request, body []byte, retryOn ...int) (*http.Re  func (t *transport) do(r *http.Request, signer func(*http.Request) error, retryOn ...int) (*http.Response, error) {  	const maxRetries = 5 -	backoff := time.Second * 2 + +	var ( +		// Initial backoff duration +		backoff = 2 * time.Second + +		// Get request hostname +		host = r.URL.Hostname() +	) + +	// Check if recently reached max retries for this host +	// so we don't need to bother reattempting it. The only +	// errors that are retried upon are server failure and +	// domain resolution type errors, so this cached result +	// indicates this server is likely having issues. +	if t.controller.badHosts.Has(host) { +		return nil, errors.New("too many failed attempts") +	}  	// Start a log entry for this request  	l := log.WithFields(kv.Fields{ @@ -155,6 +171,9 @@ func (t *transport) do(r *http.Request, signer func(*http.Request) error, retryO  		}  	} +	// Add "bad" entry for this host +	t.controller.badHosts.Set(host, struct{}{}) +  	return nil, errors.New("transport reached max retries")  }  | 
