dashboard_handler_cache_test.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package admin
  2. import (
  3. "context"
  4. "net/http"
  5. "net/http/httptest"
  6. "sync/atomic"
  7. "testing"
  8. "time"
  9. "github.com/Wei-Shaw/sub2api/internal/pkg/usagestats"
  10. "github.com/Wei-Shaw/sub2api/internal/service"
  11. "github.com/gin-gonic/gin"
  12. "github.com/stretchr/testify/require"
  13. )
  14. type dashboardUsageRepoCacheProbe struct {
  15. service.UsageLogRepository
  16. trendCalls atomic.Int32
  17. usersTrendCalls atomic.Int32
  18. }
  19. func (r *dashboardUsageRepoCacheProbe) GetUsageTrendWithFilters(
  20. ctx context.Context,
  21. startTime, endTime time.Time,
  22. granularity string,
  23. userID, apiKeyID, accountID, groupID int64,
  24. model string,
  25. requestType *int16,
  26. stream *bool,
  27. billingType *int8,
  28. ) ([]usagestats.TrendDataPoint, error) {
  29. r.trendCalls.Add(1)
  30. return []usagestats.TrendDataPoint{{
  31. Date: "2026-03-11",
  32. Requests: 1,
  33. TotalTokens: 2,
  34. Cost: 3,
  35. ActualCost: 4,
  36. }}, nil
  37. }
  38. func (r *dashboardUsageRepoCacheProbe) GetUserUsageTrend(
  39. ctx context.Context,
  40. startTime, endTime time.Time,
  41. granularity string,
  42. limit int,
  43. ) ([]usagestats.UserUsageTrendPoint, error) {
  44. r.usersTrendCalls.Add(1)
  45. return []usagestats.UserUsageTrendPoint{{
  46. Date: "2026-03-11",
  47. UserID: 1,
  48. Email: "cache@test.dev",
  49. Requests: 2,
  50. Tokens: 20,
  51. Cost: 2,
  52. ActualCost: 1,
  53. }}, nil
  54. }
  55. func resetDashboardReadCachesForTest() {
  56. dashboardTrendCache = newSnapshotCache(30 * time.Second)
  57. dashboardUsersTrendCache = newSnapshotCache(30 * time.Second)
  58. dashboardAPIKeysTrendCache = newSnapshotCache(30 * time.Second)
  59. dashboardModelStatsCache = newSnapshotCache(30 * time.Second)
  60. dashboardGroupStatsCache = newSnapshotCache(30 * time.Second)
  61. dashboardSnapshotV2Cache = newSnapshotCache(30 * time.Second)
  62. }
  63. func TestDashboardHandler_GetUsageTrend_UsesCache(t *testing.T) {
  64. t.Cleanup(resetDashboardReadCachesForTest)
  65. resetDashboardReadCachesForTest()
  66. gin.SetMode(gin.TestMode)
  67. repo := &dashboardUsageRepoCacheProbe{}
  68. dashboardSvc := service.NewDashboardService(repo, nil, nil, nil)
  69. handler := NewDashboardHandler(dashboardSvc, nil)
  70. router := gin.New()
  71. router.GET("/admin/dashboard/trend", handler.GetUsageTrend)
  72. req1 := httptest.NewRequest(http.MethodGet, "/admin/dashboard/trend?start_date=2026-03-01&end_date=2026-03-07&granularity=day", nil)
  73. rec1 := httptest.NewRecorder()
  74. router.ServeHTTP(rec1, req1)
  75. require.Equal(t, http.StatusOK, rec1.Code)
  76. require.Equal(t, "miss", rec1.Header().Get("X-Snapshot-Cache"))
  77. req2 := httptest.NewRequest(http.MethodGet, "/admin/dashboard/trend?start_date=2026-03-01&end_date=2026-03-07&granularity=day", nil)
  78. rec2 := httptest.NewRecorder()
  79. router.ServeHTTP(rec2, req2)
  80. require.Equal(t, http.StatusOK, rec2.Code)
  81. require.Equal(t, "hit", rec2.Header().Get("X-Snapshot-Cache"))
  82. require.Equal(t, int32(1), repo.trendCalls.Load())
  83. }
  84. func TestDashboardHandler_GetUserUsageTrend_UsesCache(t *testing.T) {
  85. t.Cleanup(resetDashboardReadCachesForTest)
  86. resetDashboardReadCachesForTest()
  87. gin.SetMode(gin.TestMode)
  88. repo := &dashboardUsageRepoCacheProbe{}
  89. dashboardSvc := service.NewDashboardService(repo, nil, nil, nil)
  90. handler := NewDashboardHandler(dashboardSvc, nil)
  91. router := gin.New()
  92. router.GET("/admin/dashboard/users-trend", handler.GetUserUsageTrend)
  93. req1 := httptest.NewRequest(http.MethodGet, "/admin/dashboard/users-trend?start_date=2026-03-01&end_date=2026-03-07&granularity=day&limit=8", nil)
  94. rec1 := httptest.NewRecorder()
  95. router.ServeHTTP(rec1, req1)
  96. require.Equal(t, http.StatusOK, rec1.Code)
  97. require.Equal(t, "miss", rec1.Header().Get("X-Snapshot-Cache"))
  98. req2 := httptest.NewRequest(http.MethodGet, "/admin/dashboard/users-trend?start_date=2026-03-01&end_date=2026-03-07&granularity=day&limit=8", nil)
  99. rec2 := httptest.NewRecorder()
  100. router.ServeHTTP(rec2, req2)
  101. require.Equal(t, http.StatusOK, rec2.Code)
  102. require.Equal(t, "hit", rec2.Header().Get("X-Snapshot-Cache"))
  103. require.Equal(t, int32(1), repo.usersTrendCalls.Load())
  104. }