mirror of
https://github.com/games-on-whales/LXC2Docker.git
synced 2026-10-15 12:52:04 +00:00
[PR #133] [MERGED] fix(oci): coalesce concurrent pulls of the same image ref #137
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
games-on-whales/LXC2Docker#137
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/games-on-whales/LXC2Docker/pull/133
Author: @JBailes
Created: 7/5/2026
Status: ✅ Merged
Merged: 7/5/2026
Merged by: @JBailes
Base:
main← Head:fix/coalesce-concurrent-pulls📝 Commits (1)
b1df3b2fix(oci): coalesce concurrent pulls of the same image ref📊 Changes
3 files changed (+129 additions, -2 deletions)
View changed files
📝
go.mod(+2 -2)📝
internal/lxc/manager.go(+30 -0)➕
internal/lxc/pull_coalesce_test.go(+97 -0)📄 Description
Problem
When two callers race to pull the same image ref, each independently runs
skopeo+umociinto the same OCI store path. They corrupt each other's partial layers near completion, the wreckage is cleaned up, and the pull is retried — so with a caller that re-issues the pull (e.g. an orchestrator polling on a reconcile tick, or adocker pulloverlapping a container-create auto-pull) it never converges.Observed on a real deployment pulling a ~20 GB GPU image: 7+ concurrent
skopeo copyprocesses for one ref, all writing the same path, colliding at ~16 GB every time, wiping the partial download, and restarting indefinitely — the image never landed and the box thrashed.Fix
Wrap
pullOCIin asingleflight.Groupkeyed by the image ref: the first caller runs the pull while any others block and share its result. Same ref → one pull; different refs → still parallel. This mirrors the existing per-imagetmplLockspattern used for template materialization, extending single-flighting to the pull (skopeo) itself, which is where the collision happened.golang.org/x/syncwas already an (indirect) dependency; it's now direct.Tests
internal/lxc/pull_coalesce_test.go(run under-race):A tiny
pullImplseam onManagerlets the wrapper be exercised without a real registry.Validation
Built static and hot-deployed to the affected host: the previously-piling pull now runs with exactly one skopeo and completed the full ~20 GB download+unpack on the first try.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.