Refacto load all functions

Unbounded LoadAll* loaders materialised an entire result set in one
query with no ceiling. A table that is small in development can grow
without bound in production, so these loaders were a latent memory
and query-time hazard.

Remove the LoadAll* methods from pkg/coredata and walk the cursor-
paginated LoadBy* siblings instead through a shared page.LoadAll
helper. The helper advances a MaxCursorSize forward cursor until the
result set is exhausted and concatenates the pages. It caps a single
call at MaxLoadAllPages (20) batches of 500 rows and errors past that
rather than materialising an unbounded set, so a runaway caller fails
loudly instead of exhausting memory.

Callers that genuinely need every row now express that explicitly,
and the coredata load-naming rule and docs are updated to discourage
new unbounded loaders.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
This commit is contained in:
Sacha Al Himdani
2026-06-09 19:33:36 +02:00
committed by Sacha Al Himdani
parent 853f2404a6
commit 9ab8ea2085
46 changed files with 1218 additions and 1674 deletions

View File

@@ -27,6 +27,7 @@ import (
"go.gearno.de/kit/pg"
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/iam/policy"
"go.probo.inc/probo/pkg/page"
)
type (
@@ -43,6 +44,17 @@ type (
CookieBannerTranslations []*CookieBannerTranslation
)
func (t CookieBannerTranslation) CursorKey(field CookieBannerTranslationOrderField) page.CursorKey {
switch field {
case CookieBannerTranslationOrderFieldLanguage:
return page.NewCursorKey(t.ID, t.Language)
case CookieBannerTranslationOrderFieldCreatedAt:
return page.NewCursorKey(t.ID, t.CreatedAt)
}
panic(fmt.Sprintf("unsupported order by: %s", field))
}
func (t *CookieBannerTranslation) AuthorizationAttributes(
ctx context.Context,
conn pg.Querier,
@@ -181,11 +193,12 @@ LIMIT 1;
return nil
}
func (t *CookieBannerTranslations) LoadAllByCookieBannerID(
func (t *CookieBannerTranslations) LoadByCookieBannerID(
ctx context.Context,
conn pg.Querier,
scope Scoper,
cookieBannerID gid.GID,
cursor *page.Cursor[CookieBannerTranslationOrderField],
) error {
q := `
SELECT
@@ -201,14 +214,14 @@ FROM
WHERE
%s
AND cookie_banner_id = @cookie_banner_id
ORDER BY
language ASC;
AND %s
`
q = fmt.Sprintf(q, scope.SQLFragment())
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
args := pgx.StrictNamedArgs{"cookie_banner_id": cookieBannerID}
maps.Copy(args, scope.SQLArguments())
maps.Copy(args, cursor.SQLArguments())
rows, err := conn.Query(ctx, q, args)
if err != nil {