mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-13 12:00:20 +00:00
fix(repo,service): SCALE-002 — push pagination into SQL for target/issuer/team/agent_group
Sprint 2 unified-master-audit closure. Pre-fix four service List
endpoints (target, issuer, team, agent_group) called repoFoo.List(ctx)
to fetch the full table then sliced in memory:
rows, _ := s.repo.List(ctx)
total := int64(len(rows))
start := (page - 1) * perPage
end := start + perPage
return rows[start:end], total, nil
This page-sliced in memory pattern marshals every row per request —
fine on small fleets but unacceptable for multi-tenant or large-fleet
deploys. The agent_group case was worse — the service explicitly
ignored page/perPage and returned the entire slice.
Fix:
- New ListPaginated(ctx, limit, offset) method on each of the four
repositories. Postgres implementations push LIMIT + OFFSET into
the SQL plus a SELECT COUNT(*) for the total. Mirrors the cursor
pattern already in internal/repository/postgres/certificate.go.
- Each ListPaginated normalises limit≤0→50 and offset<0→0,
matching the service-layer defaults that already existed.
- Repository interfaces grow the new method so adapters stay
swappable.
- Service List methods now call repoFoo.ListPaginated(ctx, perPage,
(page-1)*perPage) directly — no more memory-slice.
- AgentGroupService.ListAgentGroups closes the Bundle E / Audit
L-020 'page/perPage unused' gap.
Test changes:
- sliceWindow generic helper in testutil_test.go mirrors the SQL
LIMIT/OFFSET semantics for in-memory mocks.
- Six mock implementers (lifecycle_test, testutil_test x2,
agent_group_test, team_test) gain ListPaginated methods.
- TestTeamService_List_SCALE002_PaginationPropagatesToRepo pins
the page=2, perPage=3 → 3 rows of 10 invariant.
Closes SCALE-002.
This commit is contained in:
@@ -31,27 +31,28 @@ func NewAgentGroupService(
|
||||
}
|
||||
|
||||
// ListAgentGroups returns paginated agent groups (handler interface method).
|
||||
//
|
||||
// SCALE-002 closure (Sprint 2, 2026-05-16): pagination is now pushed
|
||||
// into the SQL layer via AgentGroupRepository.ListPaginated, closing
|
||||
// the Bundle E / Audit L-020 "page/perPage unused" gap.
|
||||
func (s *AgentGroupService) ListAgentGroups(ctx context.Context, page, perPage int) ([]domain.AgentGroup, int64, error) {
|
||||
// Bundle E / Audit L-020: page/perPage are unused; the underlying repo
|
||||
// List() does not yet take pagination params. Marked explicitly so
|
||||
// ineffassign sees no dead store and future maintainers see the
|
||||
// vestigial params rather than a misleading default-applied clamp.
|
||||
_ = page
|
||||
_ = perPage
|
||||
|
||||
groups, err := s.groupRepo.List(ctx)
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if perPage < 1 {
|
||||
perPage = 50
|
||||
}
|
||||
offset := (page - 1) * perPage
|
||||
groups, total, err := s.groupRepo.ListPaginated(ctx, perPage, offset)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to list agent groups: %w", err)
|
||||
}
|
||||
total := int64(len(groups))
|
||||
|
||||
var result []domain.AgentGroup
|
||||
for _, g := range groups {
|
||||
if g != nil {
|
||||
result = append(result, *g)
|
||||
}
|
||||
}
|
||||
|
||||
return result, total, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user