Loading
feat(datastore): container images, blobs, manifest relationships
Why
Step 2 of the OCI Local plan. Lands the three foundational datastores Steps 8–14 compose against: ContainerImageStore, ContainerBlobStore, ContainerManifestRelationshipStore.
What
UpsertContainerImagereturns(ContainerImage, bool, error)— full row, so Step 8/12 callers avoid a follow-upFindByID.- The Upsert/Create pattern is
INSERT ... ON CONFLICT DO NOTHING RETURNINGwith a fallback SELECT. Partitioned tables reject thexmax = 0single-trip trick (SQLSTATE 0A000); two trips on conflict is the canonical race-safe shape, matching container-registry'screateOrFind.
Context for LLM agents
Rationale
- Single-trip
xmax = 0insert detection. Rejected: SQLSTATE 0A000 on partitioned tables. Chosen: two trips on conflict. - Shared
errNilContextsentinels following theblob_storage_attachments.goprecedent verbatim. Rejected: callerserrors.Is-ing across stores cannot attribute the rejection. Chosen: per-store prefixes (errContainerBlobNilContextetc.). UpsertContainerImagereturning(int64, bool, error). Rejected: asymmetric withContainerBlobStore.Createand forces Step 8/12 to re-FindByIDwhennameorcontainer_repository_idis needed. Chosen: fullContainerImagestruct.
Non-goals
- Named-query metrics. Deferred to S03's metric helper;
TODO(#92-followup-S03)markers on each store type. - Bounded
ListByParent/ListByChild. The store enforces no LIMIT; bounding belongs at Step 12's manifest-push handler. container_manifeststore. Lands in Step 3 alongside annotations validation.- GC coordination locks. Deferred to S20 per the OCI Local plan.