@@ -21,6 +21,7 @@ type AntigravityHandler struct {
2121 svc * service.AdminService
2222 quotaRepo repository.AntigravityQuotaRepository
2323 oauthManager * antigravity.OAuthManager
24+ taskSvc * service.AntigravityTaskService
2425}
2526
2627// NewAntigravityHandler creates a new Antigravity handler
@@ -32,6 +33,11 @@ func NewAntigravityHandler(svc *service.AdminService, quotaRepo repository.Antig
3233 }
3334}
3435
36+ // SetTaskService sets the AntigravityTaskService for background task operations
37+ func (h * AntigravityHandler ) SetTaskService (taskSvc * service.AntigravityTaskService ) {
38+ h .taskSvc = taskSvc
39+ }
40+
3541// ServeHTTP routes Antigravity requests
3642// Routes:
3743// POST /antigravity/validate-token - 验证单个 refresh token
@@ -40,6 +46,8 @@ func NewAntigravityHandler(svc *service.AdminService, quotaRepo repository.Antig
4046// GET /antigravity/providers/quotas - 批量获取所有 Antigravity provider 的配额信息
4147// POST /antigravity/oauth/start - 启动 OAuth 流程
4248// GET /antigravity/oauth/callback - OAuth 回调
49+ // POST /antigravity/refresh-quotas - 强制刷新所有配额
50+ // POST /antigravity/sort-routes - 手动排序路由
4351func (h * AntigravityHandler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
4452 path := strings .TrimPrefix (r .URL .Path , "/antigravity" )
4553 path = strings .TrimSuffix (path , "/" )
@@ -58,6 +66,18 @@ func (h *AntigravityHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
5866 return
5967 }
6068
69+ // POST /antigravity/refresh-quotas - 强制刷新所有配额
70+ if len (parts ) >= 2 && parts [1 ] == "refresh-quotas" && r .Method == http .MethodPost {
71+ h .handleForceRefreshQuotas (w , r )
72+ return
73+ }
74+
75+ // POST /antigravity/sort-routes - 手动排序路由
76+ if len (parts ) >= 2 && parts [1 ] == "sort-routes" && r .Method == http .MethodPost {
77+ h .handleSortRoutes (w , r )
78+ return
79+ }
80+
6181 // GET /antigravity/providers/quotas - 批量获取配额(必须在单个 provider 路由之前匹配)
6282 if len (parts ) >= 3 && parts [1 ] == "providers" && parts [2 ] == "quotas" && r .Method == http .MethodGet {
6383 h .handleGetBatchQuotas (w , r )
@@ -368,6 +388,8 @@ type BatchQuotaResult struct {
368388}
369389
370390// GetBatchQuotas 批量获取所有 Antigravity provider 的配额信息(供 HTTP handler 和 Wails 共用)
391+ // 优先从数据库返回缓存数据,即使过期也会返回(避免 API 请求阻塞)
392+ // 配额刷新由后台任务负责
371393func (h * AntigravityHandler ) GetBatchQuotas (ctx context.Context ) (* BatchQuotaResult , error ) {
372394 // 获取所有 providers
373395 providers , err := h .svc .GetProviders ()
@@ -388,30 +410,19 @@ func (h *AntigravityHandler) GetBatchQuotas(ctx context.Context) (*BatchQuotaRes
388410 config := provider .Config .Antigravity
389411 email := config .Email
390412
391- // 尝试从数据库获取缓存的配额
413+ // 优先从数据库获取缓存的配额(无论是否过期)
392414 if email != "" && h .quotaRepo != nil {
393415 cachedQuota , err := h .quotaRepo .GetByEmail (email )
394416 if err == nil && cachedQuota != nil {
395- // 检查是否过期(10分钟)- 如果未过期,直接使用缓存
396- if time .Since (cachedQuota .UpdatedAt ).Seconds () < 600 {
397- result .Quotas [provider .ID ] = h .domainQuotaToResponse (cachedQuota )
398- continue
399- }
417+ result .Quotas [provider .ID ] = h .domainQuotaToResponse (cachedQuota )
418+ continue
400419 }
401420 }
402421
403- // 缓存过期或不存在,从 API 获取最新配额
422+ // 数据库没有缓存,尝试从 API 获取
404423 quota , err := antigravity .FetchQuotaForProvider (ctx , config .RefreshToken , config .ProjectID )
405424 if err != nil {
406- // 如果 API 失败,尝试使用过期的缓存数据
407- if email != "" && h .quotaRepo != nil {
408- cachedQuota , _ := h .quotaRepo .GetByEmail (email )
409- if cachedQuota != nil {
410- result .Quotas [provider .ID ] = h .domainQuotaToResponse (cachedQuota )
411- continue
412- }
413- }
414- // 跳过此 provider,不中断整体查询
425+ // API 失败,跳过此 provider
415426 continue
416427 }
417428
@@ -442,6 +453,33 @@ func (h *AntigravityHandler) handleGetBatchQuotas(w http.ResponseWriter, r *http
442453 writeJSON (w , http .StatusOK , result )
443454}
444455
456+ // handleForceRefreshQuotas 强制刷新所有 Antigravity 配额
457+ func (h * AntigravityHandler ) handleForceRefreshQuotas (w http.ResponseWriter , r * http.Request ) {
458+ if h .taskSvc == nil {
459+ writeJSON (w , http .StatusServiceUnavailable , map [string ]string {"error" : "task service not available" })
460+ return
461+ }
462+
463+ refreshed := h .taskSvc .ForceRefreshQuotas (r .Context ())
464+ writeJSON (w , http .StatusOK , map [string ]interface {}{
465+ "success" : true ,
466+ "refreshed" : refreshed ,
467+ })
468+ }
469+
470+ // handleSortRoutes 手动排序 Antigravity 路由
471+ func (h * AntigravityHandler ) handleSortRoutes (w http.ResponseWriter , r * http.Request ) {
472+ if h .taskSvc == nil {
473+ writeJSON (w , http .StatusServiceUnavailable , map [string ]string {"error" : "task service not available" })
474+ return
475+ }
476+
477+ h .taskSvc .SortRoutes (r .Context ())
478+ writeJSON (w , http .StatusOK , map [string ]interface {}{
479+ "success" : true ,
480+ })
481+ }
482+
445483// ============================================================================
446484// OAuth 授权处理函数
447485// ============================================================================
0 commit comments