Skip to content

Commit 95d25aa

Browse files
committed
feat(admin): stream account batch operations
1 parent c7366a4 commit 95d25aa

15 files changed

Lines changed: 1180 additions & 139 deletions

admin/handler.go

Lines changed: 310 additions & 22 deletions
Large diffs are not rendered by default.

admin/handler_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,79 @@ func TestRefreshAccountReturnsRefreshFailure(t *testing.T) {
312312
}
313313
}
314314

315+
func TestBatchRefreshAccountsReportsCounts(t *testing.T) {
316+
gin.SetMode(gin.TestMode)
317+
318+
handler := &Handler{
319+
refreshAccount: func(_ context.Context, id int64) error {
320+
if id == 8 {
321+
return errors.New("upstream unavailable")
322+
}
323+
return nil
324+
},
325+
}
326+
327+
recorder := httptest.NewRecorder()
328+
ctx, _ := gin.CreateTestContext(recorder)
329+
ctx.Request = httptest.NewRequest(http.MethodPost, "/api/admin/accounts/batch-refresh", strings.NewReader(`{"ids":[7,8,7,0]}`))
330+
331+
handler.BatchRefreshAccounts(ctx)
332+
333+
if recorder.Code != http.StatusOK {
334+
t.Fatalf("status = %d, want %d", recorder.Code, http.StatusOK)
335+
}
336+
337+
var payload map[string]any
338+
if err := json.Unmarshal(recorder.Body.Bytes(), &payload); err != nil {
339+
t.Fatalf("decode response: %v", err)
340+
}
341+
if got := payload["success"]; got != float64(1) {
342+
t.Fatalf("success = %v, want 1", got)
343+
}
344+
if got := payload["failed"]; got != float64(1) {
345+
t.Fatalf("failed = %v, want 1", got)
346+
}
347+
}
348+
349+
func TestBatchRefreshAccountsStreamsProgress(t *testing.T) {
350+
gin.SetMode(gin.TestMode)
351+
352+
handler := &Handler{
353+
refreshAccount: func(_ context.Context, id int64) error {
354+
if id == 8 {
355+
return errors.New("账号 8 不存在")
356+
}
357+
return nil
358+
},
359+
}
360+
361+
recorder := httptest.NewRecorder()
362+
ctx, _ := gin.CreateTestContext(recorder)
363+
ctx.Request = httptest.NewRequest(http.MethodPost, "/api/admin/accounts/batch-refresh?stream=true", strings.NewReader(`{"ids":[7,8]}`))
364+
365+
handler.BatchRefreshAccounts(ctx)
366+
367+
if recorder.Code != http.StatusOK {
368+
t.Fatalf("status = %d, want %d", recorder.Code, http.StatusOK)
369+
}
370+
if got := recorder.Header().Get("Content-Type"); !strings.Contains(got, "text/event-stream") {
371+
t.Fatalf("content-type = %q, want event-stream", got)
372+
}
373+
body := recorder.Body.String()
374+
for _, want := range []string{
375+
`"type":"start"`,
376+
`"type":"progress"`,
377+
`"type":"complete"`,
378+
`"action":"batch_refresh"`,
379+
`"success":1`,
380+
`"failed":1`,
381+
} {
382+
if !strings.Contains(body, want) {
383+
t.Fatalf("stream body missing %s:\n%s", want, body)
384+
}
385+
}
386+
}
387+
315388
func TestResetAccountStatusSyncsPlanMetadata(t *testing.T) {
316389
gin.SetMode(gin.TestMode)
317390

admin/responses.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type messageResponse struct {
2020
type statsResponse struct {
2121
Total int `json:"total"`
2222
Available int `json:"available"`
23+
RateLimited int `json:"rate_limited"`
2324
Error int `json:"error"`
2425
TodayRequests int64 `json:"today_requests"`
2526
}

admin/responses_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ func TestStatsResponse(t *testing.T) {
8282
resp := statsResponse{
8383
Total: 10,
8484
Available: 8,
85+
RateLimited: 1,
8586
Error: 2,
8687
TodayRequests: 1000,
8788
}
@@ -104,6 +105,9 @@ func TestStatsResponse(t *testing.T) {
104105
if available, ok := decoded["available"]; !ok || available != float64(8) {
105106
t.Errorf("expected JSON to contain \"available\" field = 8, got %v", available)
106107
}
108+
if rateLimited, ok := decoded["rate_limited"]; !ok || rateLimited != float64(1) {
109+
t.Errorf("expected JSON to contain \"rate_limited\" field = 1, got %v", rateLimited)
110+
}
107111
if errorField, ok := decoded["error"]; !ok || errorField != float64(2) {
108112
t.Errorf("expected JSON to contain \"error\" field = 2, got %v", errorField)
109113
}
@@ -307,6 +311,7 @@ func TestStatsResponseJSON(t *testing.T) {
307311
resp := statsResponse{
308312
Total: 10,
309313
Available: 8,
314+
RateLimited: 1,
310315
Error: 2,
311316
TodayRequests: 1000,
312317
}

0 commit comments

Comments
 (0)