This commit clarifies the purpose of certain environment variables by explicitly associating them with token management. The variables PIXIVFE_MAX_RETRIES, PIXIVFE_BASE_TIMEOUT, and PIXIVFE_MAX_BACKOFF_TIME are now prefixed with "TOKEN_" to better distinguish them from API-level settings. The ServerConfig struct, configuration loading, logging, and documentation have been updated accordingly.
2.6 KiB
Exponential Backoff in PixivFE
PixivFE implements exponential backoff as a strategy for handling API request failures and managing token usage. This document outlines the implementation details of this feature across two key components of the application.
Overview
Exponential backoff is a technique used to gradually increase the wait time between retries of a failed operation. In PixivFE, this technique is applied at two levels:
- API request level
- Token management level
Configuration
The ServerConfig struct in config/config.go includes fields for both API request level and token management level backoff settings.
The LoadConfig method sets default values for these settings if they are not provided through environment variables.
API request level backoff
Location: core/requests.go
PixivFE uses the retryablehttp package to implement exponential backoff for API requests. The implementation is as follows:
- A
retryablehttp.Clientis initialized in theinitfunction:
func init() {
retryClient = retryablehttp.NewClient()
retryClient.RetryMax = config.GlobalConfig.APIMaxRetries
retryClient.RetryWaitMin = config.GlobalConfig.APIBaseTimeout
retryClient.RetryWaitMax = config.GlobalConfig.APIMaxBackoffTime
retryClient.HTTPClient = utils.HttpClient
}
- The
retryRequestfunction uses this client to perform requests with automatic retries:
func retryRequest(ctx context.Context, reqFunc func(context.Context, string) (*retryablehttp.Request, error)) (SimpleHTTPResponse, error) {
// ... (function implementation)
}
Token management level backoff
Location: server/token_manager/token_manager.go
The TokenManager implements exponential backoff for individual tokens:
- In the
MarkTokenStatusmethod, when a token is marked asTimedOut, it calculates a timeout duration:timeoutDuration := time.Duration(math.Min( float64(tm.baseTimeout)*math.Pow(2, float64(token.FailureCount-1)), float64(tm.maxBackoffTime), )) - This calculation uses the
math.Powfunction to implement exponential growth based on the number of consecutive failures. - The timeout duration is also capped at a maximum value (
tm.maxBackoffTime). - The token's
TimeoutUntilis set to the current time plus this calculated duration.
This approach allows tokens that repeatedly fail increasingly longer "cool-down" periods before being used again, helping to manage rate limiting of individual tokens by the Pixiv API.