← back to Cli Printing Press
fix(cli): suppress max_pages_cap_hit warning under --latest-only (#1120)
5f2bde7fa62b2235b83cb2092a069f6b6456beaa · 2026-05-11 16:33:31 -0700 · Trevin Chow
* fix(cli): suppress max_pages_cap_hit warning under --latest-only
sync --latest-only programmatically pins maxPages=1, then emits a
sync_warning per paginated resource when the cap is hit. The flood
masks real sync_anomaly / sync_error events emitted by the same run.
Thread latestOnly through syncResource, syncDependentResources, and
syncDependentResource, and gate both cap-hit emit blocks (flat-path
and dependent-path) with !latestOnly. The break still fires
unconditionally so iteration stops. auto_refresh's syncResource call
passes latestOnly=true since it's a single-page latest-fetch.
graphql_sync.go.tmpl's cap-hit site only emits a human-friendly
stderr message and no JSON sync_warning, so no symmetric edit there.
Closes #928
* fix(cli): derive effectiveLatestOnly so --since override re-enables cap warnings
Greptile flagged a P1: my prior commit threaded the raw --latest-only
flag value into syncResource / syncDependentResources. When a user
combines --latest-only --since 7d, the mutex block at sync.go.tmpl
already declares --latest-only a no-op for the maxPages pin and emits
a stderr warning to that effect. But the raw true value still flowed
into `if !latestOnly`, silently suppressing legitimate cap-hit warnings
on the default 100-page cap — defeating the entire noise-reduction
goal in the exact scenario the issue meant to surface.
Derive `effectiveLatestOnly := latestOnly && since == ""` after the
mutex block and thread that through. Add test assertions covering the
derivation and both callsites.
Files touched
M internal/generator/generator_test.goM internal/generator/templates/auto_refresh.go.tmplM internal/generator/templates/channel_workflow.go.tmplM internal/generator/templates/sync.go.tmplM testdata/golden/expected/generate-golden-api/printing-press-golden/internal/cli/sync.goM testdata/golden/expected/generate-sync-walker-api/sync-walker-golden/internal/cli/sync.goM testdata/golden/expected/generate-tier-routing-api/tier-routing-golden/internal/cli/sync.go
Diff
commit 5f2bde7fa62b2235b83cb2092a069f6b6456beaa
Author: Trevin Chow <trevin@trevinchow.com>
Date: Mon May 11 16:33:31 2026 -0700
fix(cli): suppress max_pages_cap_hit warning under --latest-only (#1120)
* fix(cli): suppress max_pages_cap_hit warning under --latest-only
sync --latest-only programmatically pins maxPages=1, then emits a
sync_warning per paginated resource when the cap is hit. The flood
masks real sync_anomaly / sync_error events emitted by the same run.
Thread latestOnly through syncResource, syncDependentResources, and
syncDependentResource, and gate both cap-hit emit blocks (flat-path
and dependent-path) with !latestOnly. The break still fires
unconditionally so iteration stops. auto_refresh's syncResource call
passes latestOnly=true since it's a single-page latest-fetch.
graphql_sync.go.tmpl's cap-hit site only emits a human-friendly
stderr message and no JSON sync_warning, so no symmetric edit there.
Closes #928
* fix(cli): derive effectiveLatestOnly so --since override re-enables cap warnings
Greptile flagged a P1: my prior commit threaded the raw --latest-only
flag value into syncResource / syncDependentResources. When a user
combines --latest-only --since 7d, the mutex block at sync.go.tmpl
already declares --latest-only a no-op for the maxPages pin and emits
a stderr warning to that effect. But the raw true value still flowed
into `if !latestOnly`, silently suppressing legitimate cap-hit warnings
on the default 100-page cap — defeating the entire noise-reduction
goal in the exact scenario the issue meant to surface.
Derive `effectiveLatestOnly := latestOnly && since == ""` after the
mutex block and thread that through. Add test assertions covering the
derivation and both callsites.
---
internal/generator/generator_test.go | 38 +++++++++++++++++-
internal/generator/templates/auto_refresh.go.tmpl | 2 +-
.../generator/templates/channel_workflow.go.tmpl | 2 +-
internal/generator/templates/sync.go.tmpl | 45 ++++++++++++++--------
.../printing-press-golden/internal/cli/sync.go | 45 ++++++++++++++--------
.../sync-walker-golden/internal/cli/sync.go | 45 ++++++++++++++--------
.../tier-routing-golden/internal/cli/sync.go | 27 +++++++++----
7 files changed, 149 insertions(+), 55 deletions(-)
diff --git a/internal/generator/generator_test.go b/internal/generator/generator_test.go
index 82938ebe..87b29c08 100644
--- a/internal/generator/generator_test.go
+++ b/internal/generator/generator_test.go
@@ -6472,7 +6472,7 @@ func TestGenerateDependentSyncCompiles(t *testing.T) {
// where it gates each dependent.
assert.Contains(t, syncContent, "parentFilter := append([]string(nil), resources...)",
"sync.go should capture user --resources filter before default expansion")
- assert.Contains(t, syncContent, "maxPages, parentFilter",
+ assert.Contains(t, syncContent, "effectiveLatestOnly, parentFilter",
"sync.go should pass the captured filter into syncDependentResources")
assert.Contains(t, syncContent, "parentFilter []string",
"syncDependentResources should accept a parent filter")
@@ -6789,6 +6789,42 @@ func TestGeneratedSyncMaxPagesAndStickyCursor(t *testing.T) {
`{"event":"sync_warning","resource":"%s","parent":"%s","reason":"max_pages_cap_hit"`,
"dependent-resource cap-hit must emit a structured sync_warning with reason max_pages_cap_hit")
+ // (b3) Issue #928: --latest-only pins maxPages=1 programmatically, so
+ // the cap is hit on every paginated resource by user intent rather
+ // than anomaly. Both cap-hit emit blocks must sit inside an
+ // `if !latestOnly` guard, otherwise the warning flood masks real
+ // sync_anomaly / sync_error events emitted by the same run.
+ guardBefore := func(marker string) string {
+ idx := strings.Index(syncContent, marker)
+ require.NotEqualf(t, -1, idx, "marker %q must appear in generated sync.go", marker)
+ return syncContent[max(0, idx-400):idx]
+ }
+ assert.Contains(t,
+ guardBefore(`"resource":"%s","reason":"max_pages_cap_hit"`),
+ "if !latestOnly {",
+ "flat-path cap-hit emit must be guarded by `if !latestOnly` (issue #928)")
+ assert.Contains(t,
+ guardBefore(`"resource":"%s","parent":"%s","reason":"max_pages_cap_hit"`),
+ "if !latestOnly {",
+ "dependent-resource cap-hit emit must be guarded by `if !latestOnly` (issue #928)")
+
+ // (b4) The cap-hit guard must consume an effective value derived from
+ // both --latest-only AND --since. When --since is set, --latest-only is
+ // already a no-op for the maxPages pin (block at sync.go.tmpl ~154),
+ // and any cap hit reflects the default 100-page limit — a real anomaly
+ // worth surfacing. Passing the raw --latest-only flag value would
+ // silently suppress legitimate warnings on the --latest-only --since
+ // combined path. Pin the derivation and the callsites that consume it.
+ assert.Contains(t, syncContent,
+ `effectiveLatestOnly := latestOnly && since == ""`,
+ "sync.go must derive effectiveLatestOnly so --since overrides re-enable cap-hit warnings (issue #928 Greptile follow-up)")
+ assert.Contains(t, syncContent,
+ "maxPages, effectiveLatestOnly",
+ "syncResource call must pass effectiveLatestOnly, not the raw --latest-only flag (issue #928 Greptile follow-up)")
+ assert.Contains(t, syncContent,
+ "maxPages, effectiveLatestOnly, parentFilter",
+ "syncDependentResources call must pass effectiveLatestOnly, not the raw --latest-only flag (issue #928 Greptile follow-up)")
+
// (c) Sticky-cursor detection on the flat path. The check must compare
// against a tracked lastNextCursor and emit the structured warning when
// the cursor doesn't advance.
diff --git a/internal/generator/templates/auto_refresh.go.tmpl b/internal/generator/templates/auto_refresh.go.tmpl
index f9a0bb6e..3813ef59 100644
--- a/internal/generator/templates/auto_refresh.go.tmpl
+++ b/internal/generator/templates/auto_refresh.go.tmpl
@@ -189,7 +189,7 @@ func runAutoRefresh(ctx context.Context, flags *rootFlags, db *store.Store, reso
return ctx.Err()
default:
}
- result := syncResource({{if .HasTierRouting}}syncClientForResource(c, resource){{else}}c{{end}}, db, resource, "", false, 1{{if .Pagination.DateRangeParam}}, ""{{end}}{{if not (isGraphQL .APISpec)}}, nil{{end}})
+ result := syncResource({{if .HasTierRouting}}syncClientForResource(c, resource){{else}}c{{end}}, db, resource, "", false, 1{{if not (isGraphQL .APISpec)}}, true{{end}}{{if .Pagination.DateRangeParam}}, ""{{end}}{{if not (isGraphQL .APISpec)}}, nil{{end}})
if result.Err != nil {
failures = append(failures, fmt.Sprintf("%s: %v", resource, result.Err))
}
diff --git a/internal/generator/templates/channel_workflow.go.tmpl b/internal/generator/templates/channel_workflow.go.tmpl
index c63768cb..1c262a3a 100644
--- a/internal/generator/templates/channel_workflow.go.tmpl
+++ b/internal/generator/templates/channel_workflow.go.tmpl
@@ -288,7 +288,7 @@ and full resync. After archiving, use 'search' for instant full-text search.`,
}
for _, resource := range resources {
- res := syncResource({{if .HasTierRouting}}syncClientForResource(c, resource){{else}}c{{end}}, s, resource, "", full, 100{{if .Pagination.DateRangeParam}}, ""{{end}}{{if not (isGraphQL .APISpec)}}, nil{{end}})
+ res := syncResource({{if .HasTierRouting}}syncClientForResource(c, resource){{else}}c{{end}}, s, resource, "", full, 100{{if not (isGraphQL .APISpec)}}, false{{end}}{{if .Pagination.DateRangeParam}}, ""{{end}}{{if not (isGraphQL .APISpec)}}, nil{{end}})
if res.Err != nil {
fmt.Fprintf(cmd.ErrOrStderr(), " %s: error: %v\n", resource, res.Err)
continue
diff --git a/internal/generator/templates/sync.go.tmpl b/internal/generator/templates/sync.go.tmpl
index 26c7be21..68de92fe 100644
--- a/internal/generator/templates/sync.go.tmpl
+++ b/internal/generator/templates/sync.go.tmpl
@@ -167,6 +167,13 @@ Exit codes & warnings:
fmt.Fprintln(os.Stderr, "warning: --latest-only ignored because --since is set; --since takes precedence")
}
}
+ // effectiveLatestOnly drives the max_pages_cap_hit suppression
+ // below. It must reflect whether --latest-only is actually the
+ // cap source — i.e., only when --since is empty. If --since wins
+ // (block above), --latest-only is a no-op for maxPages and any
+ // cap hit reflects the default --max-pages 100 limit, which is
+ // a real anomaly worth surfacing.
+ effectiveLatestOnly := latestOnly && since == ""
// Resolve --since into an RFC3339 timestamp
sinceTS := ""
@@ -198,7 +205,7 @@ Exit codes & warnings:
go func() {
defer wg.Done()
for resource := range work {
- res := syncResource({{if .HasTierRouting}}syncClientForResource(c, resource){{else}}c{{end}}, db, resource, sinceTS, full, maxPages{{if .Pagination.DateRangeParam}}, syncDates{{end}}, userParams)
+ res := syncResource({{if .HasTierRouting}}syncClientForResource(c, resource){{else}}c{{end}}, db, resource, sinceTS, full, maxPages, effectiveLatestOnly{{if .Pagination.DateRangeParam}}, syncDates{{end}}, userParams)
results <- res
}
}()
@@ -246,7 +253,7 @@ Exit codes & warnings:
{{- if .DependentSyncResources}}
// Sync dependent (parent-child) resources sequentially after flat resources.
- depResults := syncDependentResources(c, db, sinceTS, full, maxPages, parentFilter{{if .Pagination.DateRangeParam}}, syncDates{{end}}, userParams)
+ depResults := syncDependentResources(c, db, sinceTS, full, maxPages, effectiveLatestOnly, parentFilter{{if .Pagination.DateRangeParam}}, syncDates{{end}}, userParams)
for _, res := range depResults {
if res.Err != nil {
if humanFriendly {
@@ -346,7 +353,7 @@ Exit codes & warnings:
func syncResource(c interface {
Get(string, map[string]string) (json.RawMessage, error)
RateLimit() float64
-}, db *store.Store, resource, sinceTS string, full bool, maxPages int{{if .Pagination.DateRangeParam}}, dates string{{end}}, userParams *syncUserParams) syncResult {
+}, db *store.Store, resource, sinceTS string, full bool, maxPages int, latestOnly bool{{if .Pagination.DateRangeParam}}, dates string{{end}}, userParams *syncUserParams) syncResult {
started := time.Now()
if !humanFriendly {
@@ -575,12 +582,18 @@ func syncResource(c interface {
pagesFetched++
- // Enforce page ceiling to prevent runaway syncs on large-catalog APIs
+ // Enforce page ceiling to prevent runaway syncs on large-catalog APIs.
+ // Suppress the cap-hit warning when --latest-only is the cap source:
+ // the template pinned maxPages=1 by user intent, and emitting one
+ // warning per paginated resource would mask real sync_anomaly /
+ // sync_error output in the same stream.
if maxPages > 0 && pagesFetched >= maxPages {
- if humanFriendly {
- fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items)\n", resource, maxPages, totalCount)
- } else {
- fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", resource, maxPages)
+ if !latestOnly {
+ if humanFriendly {
+ fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items)\n", resource, maxPages, totalCount)
+ } else {
+ fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", resource, maxPages)
+ }
}
break
}
@@ -1111,7 +1124,7 @@ func dependentResourceDefs() []dependentResourceDef {
func syncDependentResources(c {{if .HasTierRouting}}*client.Client{{else}}interface {
Get(string, map[string]string) (json.RawMessage, error)
RateLimit() float64
-}{{end}}, db *store.Store, sinceTS string, full bool, maxPages int, parentFilter []string{{if .Pagination.DateRangeParam}}, dates string{{end}}, userParams *syncUserParams) []syncResult {
+}{{end}}, db *store.Store, sinceTS string, full bool, maxPages int, latestOnly bool, parentFilter []string{{if .Pagination.DateRangeParam}}, dates string{{end}}, userParams *syncUserParams) []syncResult {
allow := make(map[string]bool, len(parentFilter))
for _, r := range parentFilter {
allow[r] = true
@@ -1121,7 +1134,7 @@ func syncDependentResources(c {{if .HasTierRouting}}*client.Client{{else}}interf
if len(allow) > 0 && !allow[dep.ParentTable] && !allow[dep.Name] {
continue
}
- res := syncDependentResource({{if .HasTierRouting}}syncClientForResource(c, dep.Name){{else}}c{{end}}, db, dep, sinceTS, full, maxPages{{if .Pagination.DateRangeParam}}, dates{{end}}, userParams)
+ res := syncDependentResource({{if .HasTierRouting}}syncClientForResource(c, dep.Name){{else}}c{{end}}, db, dep, sinceTS, full, maxPages, latestOnly{{if .Pagination.DateRangeParam}}, dates{{end}}, userParams)
results = append(results, res)
}
return results
@@ -1131,7 +1144,7 @@ func syncDependentResources(c {{if .HasTierRouting}}*client.Client{{else}}interf
func syncDependentResource(c interface {
Get(string, map[string]string) (json.RawMessage, error)
RateLimit() float64
-}, db *store.Store, dep dependentResourceDef, sinceTS string, full bool, maxPages int{{if .Pagination.DateRangeParam}}, dates string{{end}}, userParams *syncUserParams) syncResult {
+}, db *store.Store, dep dependentResourceDef, sinceTS string, full bool, maxPages int, latestOnly bool{{if .Pagination.DateRangeParam}}, dates string{{end}}, userParams *syncUserParams) syncResult {
started := time.Now()
// Query parent table for the keys to substitute into the child path.
@@ -1290,10 +1303,12 @@ func syncDependentResource(c interface {
pagesFetched++
if maxPages > 0 && pagesFetched >= maxPages {
- if humanFriendly {
- fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items) for parent %s\n", dep.Name, maxPages, totalCount, parentID)
- } else {
- fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","parent":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", dep.Name, parentID, maxPages)
+ if !latestOnly {
+ if humanFriendly {
+ fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items) for parent %s\n", dep.Name, maxPages, totalCount, parentID)
+ } else {
+ fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","parent":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", dep.Name, parentID, maxPages)
+ }
}
break
}
diff --git a/testdata/golden/expected/generate-golden-api/printing-press-golden/internal/cli/sync.go b/testdata/golden/expected/generate-golden-api/printing-press-golden/internal/cli/sync.go
index 56f7ba5e..041df0f6 100644
--- a/testdata/golden/expected/generate-golden-api/printing-press-golden/internal/cli/sync.go
+++ b/testdata/golden/expected/generate-golden-api/printing-press-golden/internal/cli/sync.go
@@ -153,6 +153,13 @@ Exit codes & warnings:
fmt.Fprintln(os.Stderr, "warning: --latest-only ignored because --since is set; --since takes precedence")
}
}
+ // effectiveLatestOnly drives the max_pages_cap_hit suppression
+ // below. It must reflect whether --latest-only is actually the
+ // cap source — i.e., only when --since is empty. If --since wins
+ // (block above), --latest-only is a no-op for maxPages and any
+ // cap hit reflects the default --max-pages 100 limit, which is
+ // a real anomaly worth surfacing.
+ effectiveLatestOnly := latestOnly && since == ""
// Resolve --since into an RFC3339 timestamp
sinceTS := ""
@@ -179,7 +186,7 @@ Exit codes & warnings:
go func() {
defer wg.Done()
for resource := range work {
- res := syncResource(c, db, resource, sinceTS, full, maxPages, userParams)
+ res := syncResource(c, db, resource, sinceTS, full, maxPages, effectiveLatestOnly, userParams)
results <- res
}
}()
@@ -225,7 +232,7 @@ Exit codes & warnings:
}
}
// Sync dependent (parent-child) resources sequentially after flat resources.
- depResults := syncDependentResources(c, db, sinceTS, full, maxPages, parentFilter, userParams)
+ depResults := syncDependentResources(c, db, sinceTS, full, maxPages, effectiveLatestOnly, parentFilter, userParams)
for _, res := range depResults {
if res.Err != nil {
if humanFriendly {
@@ -321,7 +328,7 @@ Exit codes & warnings:
func syncResource(c interface {
Get(string, map[string]string) (json.RawMessage, error)
RateLimit() float64
-}, db *store.Store, resource, sinceTS string, full bool, maxPages int, userParams *syncUserParams) syncResult {
+}, db *store.Store, resource, sinceTS string, full bool, maxPages int, latestOnly bool, userParams *syncUserParams) syncResult {
started := time.Now()
if !humanFriendly {
@@ -543,12 +550,18 @@ func syncResource(c interface {
pagesFetched++
- // Enforce page ceiling to prevent runaway syncs on large-catalog APIs
+ // Enforce page ceiling to prevent runaway syncs on large-catalog APIs.
+ // Suppress the cap-hit warning when --latest-only is the cap source:
+ // the template pinned maxPages=1 by user intent, and emitting one
+ // warning per paginated resource would mask real sync_anomaly /
+ // sync_error output in the same stream.
if maxPages > 0 && pagesFetched >= maxPages {
- if humanFriendly {
- fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items)\n", resource, maxPages, totalCount)
- } else {
- fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", resource, maxPages)
+ if !latestOnly {
+ if humanFriendly {
+ fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items)\n", resource, maxPages, totalCount)
+ } else {
+ fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", resource, maxPages)
+ }
}
break
}
@@ -1003,7 +1016,7 @@ func dependentResourceDefs() []dependentResourceDef {
func syncDependentResources(c interface {
Get(string, map[string]string) (json.RawMessage, error)
RateLimit() float64
-}, db *store.Store, sinceTS string, full bool, maxPages int, parentFilter []string, userParams *syncUserParams) []syncResult {
+}, db *store.Store, sinceTS string, full bool, maxPages int, latestOnly bool, parentFilter []string, userParams *syncUserParams) []syncResult {
allow := make(map[string]bool, len(parentFilter))
for _, r := range parentFilter {
allow[r] = true
@@ -1013,7 +1026,7 @@ func syncDependentResources(c interface {
if len(allow) > 0 && !allow[dep.ParentTable] && !allow[dep.Name] {
continue
}
- res := syncDependentResource(c, db, dep, sinceTS, full, maxPages, userParams)
+ res := syncDependentResource(c, db, dep, sinceTS, full, maxPages, latestOnly, userParams)
results = append(results, res)
}
return results
@@ -1023,7 +1036,7 @@ func syncDependentResources(c interface {
func syncDependentResource(c interface {
Get(string, map[string]string) (json.RawMessage, error)
RateLimit() float64
-}, db *store.Store, dep dependentResourceDef, sinceTS string, full bool, maxPages int, userParams *syncUserParams) syncResult {
+}, db *store.Store, dep dependentResourceDef, sinceTS string, full bool, maxPages int, latestOnly bool, userParams *syncUserParams) syncResult {
started := time.Now()
// Query parent table for the keys to substitute into the child path.
@@ -1177,10 +1190,12 @@ func syncDependentResource(c interface {
pagesFetched++
if maxPages > 0 && pagesFetched >= maxPages {
- if humanFriendly {
- fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items) for parent %s\n", dep.Name, maxPages, totalCount, parentID)
- } else {
- fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","parent":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", dep.Name, parentID, maxPages)
+ if !latestOnly {
+ if humanFriendly {
+ fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items) for parent %s\n", dep.Name, maxPages, totalCount, parentID)
+ } else {
+ fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","parent":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", dep.Name, parentID, maxPages)
+ }
}
break
}
diff --git a/testdata/golden/expected/generate-sync-walker-api/sync-walker-golden/internal/cli/sync.go b/testdata/golden/expected/generate-sync-walker-api/sync-walker-golden/internal/cli/sync.go
index 782a636e..f0475f0c 100644
--- a/testdata/golden/expected/generate-sync-walker-api/sync-walker-golden/internal/cli/sync.go
+++ b/testdata/golden/expected/generate-sync-walker-api/sync-walker-golden/internal/cli/sync.go
@@ -153,6 +153,13 @@ Exit codes & warnings:
fmt.Fprintln(os.Stderr, "warning: --latest-only ignored because --since is set; --since takes precedence")
}
}
+ // effectiveLatestOnly drives the max_pages_cap_hit suppression
+ // below. It must reflect whether --latest-only is actually the
+ // cap source — i.e., only when --since is empty. If --since wins
+ // (block above), --latest-only is a no-op for maxPages and any
+ // cap hit reflects the default --max-pages 100 limit, which is
+ // a real anomaly worth surfacing.
+ effectiveLatestOnly := latestOnly && since == ""
// Resolve --since into an RFC3339 timestamp
sinceTS := ""
@@ -179,7 +186,7 @@ Exit codes & warnings:
go func() {
defer wg.Done()
for resource := range work {
- res := syncResource(c, db, resource, sinceTS, full, maxPages, userParams)
+ res := syncResource(c, db, resource, sinceTS, full, maxPages, effectiveLatestOnly, userParams)
results <- res
}
}()
@@ -225,7 +232,7 @@ Exit codes & warnings:
}
}
// Sync dependent (parent-child) resources sequentially after flat resources.
- depResults := syncDependentResources(c, db, sinceTS, full, maxPages, parentFilter, userParams)
+ depResults := syncDependentResources(c, db, sinceTS, full, maxPages, effectiveLatestOnly, parentFilter, userParams)
for _, res := range depResults {
if res.Err != nil {
if humanFriendly {
@@ -321,7 +328,7 @@ Exit codes & warnings:
func syncResource(c interface {
Get(string, map[string]string) (json.RawMessage, error)
RateLimit() float64
-}, db *store.Store, resource, sinceTS string, full bool, maxPages int, userParams *syncUserParams) syncResult {
+}, db *store.Store, resource, sinceTS string, full bool, maxPages int, latestOnly bool, userParams *syncUserParams) syncResult {
started := time.Now()
if !humanFriendly {
@@ -543,12 +550,18 @@ func syncResource(c interface {
pagesFetched++
- // Enforce page ceiling to prevent runaway syncs on large-catalog APIs
+ // Enforce page ceiling to prevent runaway syncs on large-catalog APIs.
+ // Suppress the cap-hit warning when --latest-only is the cap source:
+ // the template pinned maxPages=1 by user intent, and emitting one
+ // warning per paginated resource would mask real sync_anomaly /
+ // sync_error output in the same stream.
if maxPages > 0 && pagesFetched >= maxPages {
- if humanFriendly {
- fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items)\n", resource, maxPages, totalCount)
- } else {
- fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", resource, maxPages)
+ if !latestOnly {
+ if humanFriendly {
+ fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items)\n", resource, maxPages, totalCount)
+ } else {
+ fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", resource, maxPages)
+ }
}
break
}
@@ -997,7 +1010,7 @@ func dependentResourceDefs() []dependentResourceDef {
func syncDependentResources(c interface {
Get(string, map[string]string) (json.RawMessage, error)
RateLimit() float64
-}, db *store.Store, sinceTS string, full bool, maxPages int, parentFilter []string, userParams *syncUserParams) []syncResult {
+}, db *store.Store, sinceTS string, full bool, maxPages int, latestOnly bool, parentFilter []string, userParams *syncUserParams) []syncResult {
allow := make(map[string]bool, len(parentFilter))
for _, r := range parentFilter {
allow[r] = true
@@ -1007,7 +1020,7 @@ func syncDependentResources(c interface {
if len(allow) > 0 && !allow[dep.ParentTable] && !allow[dep.Name] {
continue
}
- res := syncDependentResource(c, db, dep, sinceTS, full, maxPages, userParams)
+ res := syncDependentResource(c, db, dep, sinceTS, full, maxPages, latestOnly, userParams)
results = append(results, res)
}
return results
@@ -1017,7 +1030,7 @@ func syncDependentResources(c interface {
func syncDependentResource(c interface {
Get(string, map[string]string) (json.RawMessage, error)
RateLimit() float64
-}, db *store.Store, dep dependentResourceDef, sinceTS string, full bool, maxPages int, userParams *syncUserParams) syncResult {
+}, db *store.Store, dep dependentResourceDef, sinceTS string, full bool, maxPages int, latestOnly bool, userParams *syncUserParams) syncResult {
started := time.Now()
// Query parent table for the keys to substitute into the child path.
@@ -1171,10 +1184,12 @@ func syncDependentResource(c interface {
pagesFetched++
if maxPages > 0 && pagesFetched >= maxPages {
- if humanFriendly {
- fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items) for parent %s\n", dep.Name, maxPages, totalCount, parentID)
- } else {
- fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","parent":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", dep.Name, parentID, maxPages)
+ if !latestOnly {
+ if humanFriendly {
+ fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items) for parent %s\n", dep.Name, maxPages, totalCount, parentID)
+ } else {
+ fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","parent":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", dep.Name, parentID, maxPages)
+ }
}
break
}
diff --git a/testdata/golden/expected/generate-tier-routing-api/tier-routing-golden/internal/cli/sync.go b/testdata/golden/expected/generate-tier-routing-api/tier-routing-golden/internal/cli/sync.go
index 973de6a2..6d4386f0 100644
--- a/testdata/golden/expected/generate-tier-routing-api/tier-routing-golden/internal/cli/sync.go
+++ b/testdata/golden/expected/generate-tier-routing-api/tier-routing-golden/internal/cli/sync.go
@@ -151,6 +151,13 @@ Exit codes & warnings:
fmt.Fprintln(os.Stderr, "warning: --latest-only ignored because --since is set; --since takes precedence")
}
}
+ // effectiveLatestOnly drives the max_pages_cap_hit suppression
+ // below. It must reflect whether --latest-only is actually the
+ // cap source — i.e., only when --since is empty. If --since wins
+ // (block above), --latest-only is a no-op for maxPages and any
+ // cap hit reflects the default --max-pages 100 limit, which is
+ // a real anomaly worth surfacing.
+ effectiveLatestOnly := latestOnly && since == ""
// Resolve --since into an RFC3339 timestamp
sinceTS := ""
@@ -177,7 +184,7 @@ Exit codes & warnings:
go func() {
defer wg.Done()
for resource := range work {
- res := syncResource(syncClientForResource(c, resource), db, resource, sinceTS, full, maxPages, userParams)
+ res := syncResource(syncClientForResource(c, resource), db, resource, sinceTS, full, maxPages, effectiveLatestOnly, userParams)
results <- res
}
}()
@@ -295,7 +302,7 @@ Exit codes & warnings:
func syncResource(c interface {
Get(string, map[string]string) (json.RawMessage, error)
RateLimit() float64
-}, db *store.Store, resource, sinceTS string, full bool, maxPages int, userParams *syncUserParams) syncResult {
+}, db *store.Store, resource, sinceTS string, full bool, maxPages int, latestOnly bool, userParams *syncUserParams) syncResult {
started := time.Now()
if !humanFriendly {
@@ -517,12 +524,18 @@ func syncResource(c interface {
pagesFetched++
- // Enforce page ceiling to prevent runaway syncs on large-catalog APIs
+ // Enforce page ceiling to prevent runaway syncs on large-catalog APIs.
+ // Suppress the cap-hit warning when --latest-only is the cap source:
+ // the template pinned maxPages=1 by user intent, and emitting one
+ // warning per paginated resource would mask real sync_anomaly /
+ // sync_error output in the same stream.
if maxPages > 0 && pagesFetched >= maxPages {
- if humanFriendly {
- fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items)\n", resource, maxPages, totalCount)
- } else {
- fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", resource, maxPages)
+ if !latestOnly {
+ if humanFriendly {
+ fmt.Fprintf(os.Stderr, "\n %s: reached --max-pages limit (%d pages, %d items)\n", resource, maxPages, totalCount)
+ } else {
+ fmt.Fprintf(os.Stdout, `{"event":"sync_warning","resource":"%s","reason":"max_pages_cap_hit","message":"reached --max-pages cap of %d; data may be truncated. Re-run with --max-pages 0 (unlimited) or higher to verify."}`+"\n", resource, maxPages)
+ }
}
break
}
← 10cc48a8 fix(cli): infer pagination defaults from plain params; prese
·
back to Cli Printing Press
·
fix(cli): exempt CLI-root vendor spec files from PII audit s 6536cfff →