@@ -88,8 +88,9 @@ func (r *groupRepository) GetByID(ctx context.Context, id int64) (*service.Group
8888 if err != nil {
8989 return nil , err
9090 }
91- count , _ := r .GetAccountCount (ctx , out .ID )
92- out .AccountCount = count
91+ total , active , _ := r .GetAccountCount (ctx , out .ID )
92+ out .AccountCount = total
93+ out .ActiveAccountCount = active
9394 return out , nil
9495}
9596
@@ -256,7 +257,10 @@ func (r *groupRepository) ListWithFilters(ctx context.Context, params pagination
256257 counts , err := r .loadAccountCounts (ctx , groupIDs )
257258 if err == nil {
258259 for i := range outGroups {
259- outGroups [i ].AccountCount = counts [outGroups [i ].ID ]
260+ c := counts [outGroups [i ].ID ]
261+ outGroups [i ].AccountCount = c .Total
262+ outGroups [i ].ActiveAccountCount = c .Active
263+ outGroups [i ].RateLimitedAccountCount = c .RateLimited
260264 }
261265 }
262266
@@ -283,7 +287,10 @@ func (r *groupRepository) ListActive(ctx context.Context) ([]service.Group, erro
283287 counts , err := r .loadAccountCounts (ctx , groupIDs )
284288 if err == nil {
285289 for i := range outGroups {
286- outGroups [i ].AccountCount = counts [outGroups [i ].ID ]
290+ c := counts [outGroups [i ].ID ]
291+ outGroups [i ].AccountCount = c .Total
292+ outGroups [i ].ActiveAccountCount = c .Active
293+ outGroups [i ].RateLimitedAccountCount = c .RateLimited
287294 }
288295 }
289296
@@ -310,7 +317,10 @@ func (r *groupRepository) ListActiveByPlatform(ctx context.Context, platform str
310317 counts , err := r .loadAccountCounts (ctx , groupIDs )
311318 if err == nil {
312319 for i := range outGroups {
313- outGroups [i ].AccountCount = counts [outGroups [i ].ID ]
320+ c := counts [outGroups [i ].ID ]
321+ outGroups [i ].AccountCount = c .Total
322+ outGroups [i ].ActiveAccountCount = c .Active
323+ outGroups [i ].RateLimitedAccountCount = c .RateLimited
314324 }
315325 }
316326
@@ -369,12 +379,20 @@ func (r *groupRepository) ExistsByIDs(ctx context.Context, ids []int64) (map[int
369379 return result , nil
370380}
371381
372- func (r * groupRepository ) GetAccountCount (ctx context.Context , groupID int64 ) (int64 , error ) {
373- var count int64
374- if err := scanSingleRow (ctx , r .sql , "SELECT COUNT(*) FROM account_groups WHERE group_id = $1" , []any {groupID }, & count ); err != nil {
375- return 0 , err
376- }
377- return count , nil
382+ func (r * groupRepository ) GetAccountCount (ctx context.Context , groupID int64 ) (total int64 , active int64 , err error ) {
383+ var rateLimited int64
384+ err = scanSingleRow (ctx , r .sql ,
385+ `SELECT COUNT(*),
386+ COUNT(*) FILTER (WHERE a.status = 'active' AND a.schedulable = true),
387+ COUNT(*) FILTER (WHERE a.status = 'active' AND (
388+ a.rate_limit_reset_at > NOW() OR
389+ a.overload_until > NOW() OR
390+ a.temp_unschedulable_until > NOW()
391+ ))
392+ FROM account_groups ag JOIN accounts a ON a.id = ag.account_id
393+ WHERE ag.group_id = $1` ,
394+ []any {groupID }, & total , & active , & rateLimited )
395+ return
378396}
379397
380398func (r * groupRepository ) DeleteAccountGroupsByGroupID (ctx context.Context , groupID int64 ) (int64 , error ) {
@@ -500,15 +518,32 @@ func (r *groupRepository) DeleteCascade(ctx context.Context, id int64) ([]int64,
500518 return affectedUserIDs , nil
501519}
502520
503- func (r * groupRepository ) loadAccountCounts (ctx context.Context , groupIDs []int64 ) (counts map [int64 ]int64 , err error ) {
504- counts = make (map [int64 ]int64 , len (groupIDs ))
521+ type groupAccountCounts struct {
522+ Total int64
523+ Active int64
524+ RateLimited int64
525+ }
526+
527+ func (r * groupRepository ) loadAccountCounts (ctx context.Context , groupIDs []int64 ) (counts map [int64 ]groupAccountCounts , err error ) {
528+ counts = make (map [int64 ]groupAccountCounts , len (groupIDs ))
505529 if len (groupIDs ) == 0 {
506530 return counts , nil
507531 }
508532
509533 rows , err := r .sql .QueryContext (
510534 ctx ,
511- "SELECT group_id, COUNT(*) FROM account_groups WHERE group_id = ANY($1) GROUP BY group_id" ,
535+ `SELECT ag.group_id,
536+ COUNT(*) AS total,
537+ COUNT(*) FILTER (WHERE a.status = 'active' AND a.schedulable = true) AS active,
538+ COUNT(*) FILTER (WHERE a.status = 'active' AND (
539+ a.rate_limit_reset_at > NOW() OR
540+ a.overload_until > NOW() OR
541+ a.temp_unschedulable_until > NOW()
542+ )) AS rate_limited
543+ FROM account_groups ag
544+ JOIN accounts a ON a.id = ag.account_id
545+ WHERE ag.group_id = ANY($1)
546+ GROUP BY ag.group_id` ,
512547 pq .Array (groupIDs ),
513548 )
514549 if err != nil {
@@ -523,11 +558,11 @@ func (r *groupRepository) loadAccountCounts(ctx context.Context, groupIDs []int6
523558
524559 for rows .Next () {
525560 var groupID int64
526- var count int64
527- if err = rows .Scan (& groupID , & count ); err != nil {
561+ var c groupAccountCounts
562+ if err = rows .Scan (& groupID , & c . Total , & c . Active , & c . RateLimited ); err != nil {
528563 return nil , err
529564 }
530- counts [groupID ] = count
565+ counts [groupID ] = c
531566 }
532567 if err = rows .Err (); err != nil {
533568 return nil , err
0 commit comments