mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-04-18 12:23:44 +00:00
feat(misc): add background updater for Antigravity version caching
Introduce `StartAntigravityVersionUpdater` to periodically refresh the cached Antigravity version using a non-blocking background process. Updated main server flow to initialize the updater.
This commit is contained in:
@@ -502,6 +502,7 @@ func main() {
|
||||
if standalone {
|
||||
// Standalone mode: start an embedded local server and connect TUI client to it.
|
||||
managementasset.StartAutoUpdater(context.Background(), configFilePath)
|
||||
misc.StartAntigravityVersionUpdater(context.Background())
|
||||
if !localModel {
|
||||
registry.StartModelsUpdater(context.Background())
|
||||
}
|
||||
@@ -577,6 +578,7 @@ func main() {
|
||||
} else {
|
||||
// Start the main proxy service
|
||||
managementasset.StartAutoUpdater(context.Background(), configFilePath)
|
||||
misc.StartAntigravityVersionUpdater(context.Background())
|
||||
if !localModel {
|
||||
registry.StartModelsUpdater(context.Background())
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
package misc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
@@ -24,14 +26,69 @@ type antigravityRelease struct {
|
||||
}
|
||||
|
||||
var (
|
||||
cachedAntigravityVersion string
|
||||
cachedAntigravityVersion = antigravityFallbackVersion
|
||||
antigravityVersionMu sync.RWMutex
|
||||
antigravityVersionExpiry time.Time
|
||||
antigravityUpdaterOnce sync.Once
|
||||
)
|
||||
|
||||
// AntigravityLatestVersion returns the latest antigravity version from the releases API.
|
||||
// It caches the result for antigravityVersionCacheTTL and falls back to antigravityFallbackVersion
|
||||
// if the fetch fails.
|
||||
// StartAntigravityVersionUpdater starts a background goroutine that periodically refreshes the cached antigravity version.
|
||||
// This is intentionally decoupled from request execution to avoid blocking executors on version lookups.
|
||||
func StartAntigravityVersionUpdater(ctx context.Context) {
|
||||
antigravityUpdaterOnce.Do(func() {
|
||||
go runAntigravityVersionUpdater(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
func runAntigravityVersionUpdater(ctx context.Context) {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(antigravityVersionCacheTTL / 2)
|
||||
defer ticker.Stop()
|
||||
|
||||
log.Infof("periodic antigravity version refresh started (interval=%s)", antigravityVersionCacheTTL/2)
|
||||
|
||||
refreshAntigravityVersion(ctx)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
refreshAntigravityVersion(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshAntigravityVersion(ctx context.Context) {
|
||||
version, errFetch := fetchAntigravityLatestVersion(ctx)
|
||||
|
||||
antigravityVersionMu.Lock()
|
||||
defer antigravityVersionMu.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
|
||||
if errFetch == nil {
|
||||
cachedAntigravityVersion = version
|
||||
antigravityVersionExpiry = now.Add(antigravityVersionCacheTTL)
|
||||
log.WithField("version", version).Info("fetched latest antigravity version")
|
||||
return
|
||||
}
|
||||
|
||||
if cachedAntigravityVersion == "" || now.After(antigravityVersionExpiry) {
|
||||
cachedAntigravityVersion = antigravityFallbackVersion
|
||||
antigravityVersionExpiry = now.Add(antigravityVersionCacheTTL)
|
||||
log.WithError(errFetch).Warn("failed to refresh antigravity version, using fallback version")
|
||||
return
|
||||
}
|
||||
|
||||
log.WithError(errFetch).Debug("failed to refresh antigravity version, keeping cached value")
|
||||
}
|
||||
|
||||
// AntigravityLatestVersion returns the cached antigravity version refreshed by StartAntigravityVersionUpdater.
|
||||
// It falls back to antigravityFallbackVersion if the cache is empty or stale.
|
||||
func AntigravityLatestVersion() string {
|
||||
antigravityVersionMu.RLock()
|
||||
if cachedAntigravityVersion != "" && time.Now().Before(antigravityVersionExpiry) {
|
||||
@@ -41,18 +98,7 @@ func AntigravityLatestVersion() string {
|
||||
}
|
||||
antigravityVersionMu.RUnlock()
|
||||
|
||||
antigravityVersionMu.Lock()
|
||||
defer antigravityVersionMu.Unlock()
|
||||
|
||||
// Double-check after acquiring write lock.
|
||||
if cachedAntigravityVersion != "" && time.Now().Before(antigravityVersionExpiry) {
|
||||
return cachedAntigravityVersion
|
||||
}
|
||||
|
||||
version := fetchAntigravityLatestVersion()
|
||||
cachedAntigravityVersion = version
|
||||
antigravityVersionExpiry = time.Now().Add(antigravityVersionCacheTTL)
|
||||
return version
|
||||
return antigravityFallbackVersion
|
||||
}
|
||||
|
||||
// AntigravityUserAgent returns the User-Agent string for antigravity requests
|
||||
@@ -61,37 +107,45 @@ func AntigravityUserAgent() string {
|
||||
return fmt.Sprintf("antigravity/%s darwin/arm64", AntigravityLatestVersion())
|
||||
}
|
||||
|
||||
func fetchAntigravityLatestVersion() string {
|
||||
client := &http.Client{Timeout: antigravityFetchTimeout}
|
||||
resp, err := client.Get(antigravityReleasesURL)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("failed to fetch antigravity releases, using fallback version")
|
||||
return antigravityFallbackVersion
|
||||
func fetchAntigravityLatestVersion(ctx context.Context) (string, error) {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
client := &http.Client{Timeout: antigravityFetchTimeout}
|
||||
|
||||
httpReq, errReq := http.NewRequestWithContext(ctx, http.MethodGet, antigravityReleasesURL, nil)
|
||||
if errReq != nil {
|
||||
return "", fmt.Errorf("build antigravity releases request: %w", errReq)
|
||||
}
|
||||
|
||||
resp, errDo := client.Do(httpReq)
|
||||
if errDo != nil {
|
||||
return "", fmt.Errorf("fetch antigravity releases: %w", errDo)
|
||||
}
|
||||
defer func() {
|
||||
if errClose := resp.Body.Close(); errClose != nil {
|
||||
log.WithError(errClose).Warn("antigravity releases response body close error")
|
||||
}
|
||||
}()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.WithField("status", resp.StatusCode).Warn("antigravity releases API returned non-200, using fallback version")
|
||||
return antigravityFallbackVersion
|
||||
return "", fmt.Errorf("antigravity releases API returned status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var releases []antigravityRelease
|
||||
if err := json.NewDecoder(resp.Body).Decode(&releases); err != nil {
|
||||
log.WithError(err).Warn("failed to decode antigravity releases response, using fallback version")
|
||||
return antigravityFallbackVersion
|
||||
if errDecode := json.NewDecoder(resp.Body).Decode(&releases); errDecode != nil {
|
||||
return "", fmt.Errorf("decode antigravity releases response: %w", errDecode)
|
||||
}
|
||||
|
||||
if len(releases) == 0 {
|
||||
log.Warn("antigravity releases API returned empty list, using fallback version")
|
||||
return antigravityFallbackVersion
|
||||
return "", errors.New("antigravity releases API returned empty list")
|
||||
}
|
||||
|
||||
version := releases[0].Version
|
||||
if version == "" {
|
||||
log.Warn("antigravity releases API returned empty version, using fallback version")
|
||||
return antigravityFallbackVersion
|
||||
return "", errors.New("antigravity releases API returned empty version")
|
||||
}
|
||||
|
||||
log.WithField("version", version).Info("fetched latest antigravity version")
|
||||
return version
|
||||
return version, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user