Skip to content

Address pushes API review findings - #385

Closed
chruffins wants to merge 1 commit into
hypeship/registry-push-apifrom
hypeship/pushes-review-fixes
Closed

Address pushes API review findings#385
chruffins wants to merge 1 commit into
hypeship/registry-push-apifrom
hypeship/pushes-review-fixes

Conversation

@chruffins

@chruffins chruffins commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Addresses the review findings on #353, apart from the retention/pagination question (deferred, matches repo-wide precedent).

Bugs

  • lib/imagepush/manager.go — each push now runs under context.WithTimeout(pushTimeout) so a wedged registry can't pin a queue slot forever (default concurrency is 2).

Dead code removed

  • WaitForPush + the whole subscriber/notify machinery (subscribers, StatusEvent, subscribe/unsubscribe/notify) had no production caller — only tests. Removed them and the WaitForPush/InProgressDigests entries from the Manager interface. LiveCacheManifestDigests (the ocicachegc.RootsProvider method) stays as the single GC root source; the in-memory digest lookup is now an unexported inProgressDigests. Tests now poll GetPush via a waitTerminal helper.

Dedup simplification

  • Removed the waitForInflightRelease 5ms spin-wait and the waiter-into-successor dance built to handle the rare "terminal write failed, record dropped" window. Dedup still merges concurrent creates for the same key under the lock; in the residual mid-finalization window a create returns a clear retryable error instead of orchestrating a successor. The inflight map (needed for GC roots) is unchanged.

Structural

  • credFingerprint now normalizes the precomputed base64 Auth shorthand into username/password so the same login hashes identically either way (previously the two forms produced different fingerprints).
  • Extracted toPushWithPosition shared by GetPush/ListPushes so the domain projection + queue-position enrichment can't drift between them.
  • Factored the record-or-remove-on-write-failure logic duplicated between the panic handler and the normal completion path into persistTerminal.

Nits

  • pushToOAPI gates layers/bytes presence on status == pushed instead of value > 0.
  • writeMetadata now fsyncs the containing directory after the rename so a crash can't lose the directory entry.

Deferred

  • Queue consolidationlib/builds/BuildQueue has a materially richer contract (serial keys, cancel, per-key queries, metrics callbacks) than the extracted lib/queue; folding it is a cross-cutting change to the build subsystem and is better done as its own PR (already ticketed). Not folded here.
  • Retention/pagination for ListPushes — deferred, matches repo-wide precedent.

Verification

  • go test -race ./lib/imagepush/ ./lib/queue/ pass.
  • lib/images and cmd/api/api can't be exercised in this sandbox (build binary / local builder registry required) — cmd/api/api/pushes.go change is a syntax-checked status-gate only.

Note

Medium Risk
Changes core push job lifecycle, dedup, and persistence; bounded concurrency and OCI cache GC depend on correct in-flight digest tracking, though behavior is largely simplification plus defensive timeouts.

Overview
Addresses pushes API review feedback by tightening image push reliability and trimming unused surface area.

Each registry export now runs under a 30-minute timeout so a hung remote cannot hold a bounded queue slot indefinitely. Terminal outcomes (including panics) go through shared persistTerminal logic, and push metadata writes fsync the parent directory after rename so directory entries survive a crash.

WaitForPush, subscriber/notify machinery, and InProgressDigests on the public Manager interface are removed (no production callers). GC roots stay on LiveCacheManifestDigests only; tests poll GetPush via waitTerminal. In-flight dedup no longer spins waiting on torn-down records—during the rare post-write-failure window CreatePush returns a clear retryable error instead of orchestrating a successor job.

credFingerprint normalizes base64 Auth shorthand to username/password so equivalent logins dedupe correctly. toPushWithPosition is shared by GetPush / ListPushes. pushToOAPI exposes layers / bytes only when status is pushed, not when values are merely non-zero.

Reviewed by Cursor Bugbot for commit 13a1a28. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 13a1a28. Configure here.

Comment thread lib/imagepush/manager.go
// clear retryable error rather than orchestrating this caller into
// a successor job that does not yet exist. A retry once the entry
// drops creates a fresh job.
return nil, fmt.Errorf("%w: push job %s is being finalized after a record write failure; retry", ErrNotFound, id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finalize retry mapped as 500

Low Severity

CreatePush now returns a wrapped ErrNotFound in the mid-finalization window and documents it as retryable, but the HTTP handler only special-cases images.ErrNotFound. That path falls through to internal_error 500 instead of a clear retryable API status.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 13a1a28. Configure here.

@chruffins chruffins closed this Aug 10, 2026
@chruffins
chruffins deleted the hypeship/pushes-review-fixes branch August 10, 2026 19:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant