Add registry field to ImageGQL node
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 17h 7m
- Merged PRs (30d)
- 358
Description
Background
`ImageGQL` (`src/ai/backend/manager/api/gql/image/types.py`) currently has no resolver for the container registry that owns the image. Line 278 has an explicit TODO comment:
```
1. Registry (ContainerRegistryNode connection to be added later)
```
Without this field, GraphQL consumers must perform a separate query to resolve registry metadata for each image, and operators cannot quickly identify the registry an image belongs to when investigating dangling FK situations (e.g., the recent incident where a container registry was deleted while images still referenced it, leaving sessions stuck in SCHEDULED).
Proposed Change
1. Add a `registry: ContainerRegistryGQL | None` field to `ImageGQL`. Nullable to express the orphan/dangling-FK case explicitly rather than raising.
2. Use `strawberry.lazy()` for the cross-entity reference to `ContainerRegistryGQL` to avoid circular imports (per `api/gql/CLAUDE.md`).
3. Implement a `ContainerRegistryByImageLoader` (or reuse the existing container_registry DataLoader keyed by registry ID) so that selecting `registry` over a connection of images batches into one SQL query.
4. The resolver pulls `registry_id` off the underlying `ImageData` DTO and delegates to `info.context.data_loaders.container_registry_loader.load(registry_id)`. If the loader returns `None` (dangling FK), expose `None` instead of raising — this is the diagnostic value of the field.
5. Mark the new field with `added_version=NEXT_RELEASE_VERSION` via `gql_added_field` / `BackendAIGQLMeta`.
6. Remove the TODO comment on `image/types.py:278`.
Out of Scope
- Forward direction `ContainerRegistry.images` connection (covered by a separate story).
- Legacy `gql_legacy/image.py` graphene type — v2 only.
- Cascading delete / referential-integrity work for registry removal.
Acceptance Criteria
- `ImageGQL.registry` returns a `ContainerRegistryV2 | None` value.
- Returns `None` (does NOT raise) when the referenced registry row has been deleted.
- DataLoader batching verified — selecting `registry` over a connection of images issues a single SQL query for all unique registry IDs.
- Unit test covers: (a) image with valid registry returns full ContainerRegistryV2, (b) image with deleted registry returns null, (c) batched query for N images with K distinct registries issues one SQL.
- TODO comment removed from `api/gql/image/types.py:278`.
- Manual GraphQL verification: `{ adminImagesV2 { edges { node { id registry { url registryName } } } } }` returns expected results.
JIRA Issue: BA-6014
Contributor guide
Assessment
This issue has not been assessed yet.