diff --git a/02-DECISIONS/0251-the-registries-say-what-they-hold-and-keep-what-is-named-and-a-machine-keeps-the-image-it-runs-and-the-one-before.md b/02-DECISIONS/0251-the-registries-say-what-they-hold-and-keep-what-is-named-and-a-machine-keeps-the-image-it-runs-and-the-one-before.md index 76bec15a..ca205303 100644 --- a/02-DECISIONS/0251-the-registries-say-what-they-hold-and-keep-what-is-named-and-a-machine-keeps-the-image-it-runs-and-the-one-before.md +++ b/02-DECISIONS/0251-the-registries-say-what-they-hold-and-keep-what-is-named-and-a-machine-keeps-the-image-it-runs-and-the-one-before.md @@ -44,7 +44,10 @@ registry, and pruning of unused images on a machine — each a dry run unless as in three steps ([ADR 0246](0246-a-seats-new-verb-is-promised-before-it-is-required.md)), and the store has one holder and no second in view. Not now; the tools can be promoted when a second holder exists. -2. **The store module's own tools, in Go.** Chosen. They replace the TypeScript client nothing builds. +2. **A module's own tools, in Go, on the machine that holds the store.** Chosen. Not the store module + itself: a module that provides the artifact store may not build an artifact, because building + publishes to the store, so the tools are a second module, `artifact-store-tools`, assigned beside the + store. The store module's unbuilt TypeScript client goes. 3. *The controller's verbs.* The controller holds the records but not the store's files; the store may move to a machine the controller is not on. Rejected for everything except what only the records can answer. @@ -52,7 +55,7 @@ registry, and pruning of unused images on a machine — each a dry run unless as **For what the store tools read.** The store's door lists repositories and tags, but not a manifest no tag names — and since the mesh pins by digest, that is almost every manifest. Only the store's files list them, with each blob's size. So the tools read the store's own files, read-only, through the -store's own container, and read each manifest's content through the door. The registry's own +store's own container, manifests' content included. The registry's own `garbage-collect --dry-run` was weighed and rejected as the source: it says what is unmarked, but not how large, and not what letting go of a manifest would free. @@ -84,29 +87,33 @@ decides. ## Decision -**1. The store module answers for the store, with four tools of its own.** The distribution module, -holder of `mesh-artifact-store`, serves a Go bundle in place of its unbuilt TypeScript: +**1. A module beside the store answers for it, with four tools.** The module `artifact-store-tools`, +assigned to the machine that holds `mesh-artifact-store`, serves a Go bundle. The store module itself +cannot carry it, because a module providing the artifact store may not build an artifact; and the +tools are named for the artifact store, because *store* alone is the database server: -- `store_repositories` — every repository, its tags, how many manifests it holds and its size; -- `store_usage` — the store's size, the largest repositories, what blobs are shared, and what the +- `artifact_store_repositories` — every repository, its tags, how many manifests it holds and its size; +- `artifact_store_usage` — the store's size, the largest repositories, what blobs are shared, and what the store's nightly collector would free now; -- `store_references` — what the records say of each manifest the store holds (below), and what the +- `artifact_store_references` — what the records say of each manifest the store holds (below), and what the records keep that the store does not hold; -- `store_collect` — a dry run unless `dry_run` is false; a real run needs `why`. +- `artifact_store_collect` — a dry run unless `dry_run` is false; a real run needs `why`. -The tools read the store's files through the store's own container and only read them. The first three -change nothing; `store_collect` changes nothing either, unless it is a real run, and then only by asking +The tools read the store's files, manifests included, through the store's own container and only read +them. The first three +change nothing; `artifact_store_collect` changes nothing either, unless it is a real run, and then only by asking the controller (point 3). **2. The records are asked, never copied.** A new controller verb, `artifacts`, answers every reference the mesh recorded making, with its state: *kept* because a definition names it, *kept* because it belongs to one of the five most recent builds of a module the mesh holds, *eligible* (made, -not kept, not yet let go), or — when asked — *collected*. `store_references` sets that beside what the +not kept, not yet let go), or — when asked — *collected*. `artifact_store_references` sets that beside what the store holds and says, for every manifest, one of: - **kept**, with the reason; - **a holder of a kept archive** (the manifest that keeps an archive's blob, [issue 253](../04-ISSUES/253-the-stores-collector-would-delete-every-archive-the-mesh-keeps/00-report.md)); - **eligible**, or a holder of an eligible archive; +- **let go of, yet present** — the controller recorded letting it go and the store still holds it; - **a named document** — something the controller keeps under a tag (to-be 45 §9); - **unrecorded** — no record names it. @@ -116,7 +123,7 @@ record.** ADR 0189 §3 stands as written. **3. Collecting on demand is the same sweep, asked by a person.** A new controller verb, `collect`, says what the sweep would let go of, and does it only with `confirm` and a `why`. A real run holds every kept archive before it lets anything go, exactly as the sweep after a build does; it is bounded by a -count and a time, says what it left; and it is recorded as a hand-act with its `why`. `store_collect`'s +count and a time, says what it left; and it is recorded as a hand-act with its `why`. `artifact_store_collect`'s dry run adds what only the store knows: how many bytes the nightly collector would free once those manifests are gone, beside what it would free tonight anyway. Its real run asks `collect`. Bytes are still reclaimed by the nightly collector, because only it runs with the store held still. diff --git a/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md b/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md index 11e863a4..86518bf0 100644 --- a/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md +++ b/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md @@ -3,7 +3,7 @@ layer: to-be status: in-progress code: - mesh-controller cmd/mesh-controller (the verbs artifacts, collect and images) - - mesh-catalog modules/distribution (the store's tools) + - mesh-catalog modules/artifact-store-tools (the store's tools), modules/distribution (its unbuilt code removed) - mesh-catalog modules/gitea (package retention) - mesh-catalog modules/docker (image pruning) updated: 2026-10-08 @@ -28,9 +28,10 @@ extending [ADR 0189](../../02-DECISIONS/0189-the-store-keeps-what-the-records-na controller (records) artifacts ──┐ collect ──┐ images ──┐ │ │ │ - store module ─────┴─────────────┘ │ - (store_repositories, store_usage, │ - store_references, store_collect) │ + ┌─────────────────┴─────────────┘ │ + artifact-store-tools │ + (artifact_store_repositories, _usage, │ + _references, _collect) │ │ reads the store's files │ │ through its own container │ ▼ │ @@ -52,7 +53,8 @@ extending [ADR 0189](../../02-DECISIONS/0189-the-store-keeps-what-the-records-na The store keeps each blob once, named by its digest, with its size on disk. Each repository lists the manifests it holds (every one, whether a tag names it or not), its tags, and the layers it may serve. The tools list those files through the store's own container, read-only, and read each manifest's -content through the store's door. Nothing is written. +content the same way. Nothing is written. The tools are their own module, `artifact-store-tools`, +assigned to the machine that holds the store: the store's module may not build an artifact itself. From that, a manifest *marks* its own blob, its configuration and each layer, and an index marks the manifests it lists. The store's nightly collector removes every blob no manifest marks. The tools work @@ -60,15 +62,15 @@ the same mark, so their numbers are the collector's. ### What each tool answers -- **`store_repositories`** — each repository with its tags, its manifest count and its size: the sum of +- **`artifact_store_repositories`** — each repository with its tags, its manifest count and its size: the sum of the blobs its manifests mark. A blob shared by two repositories is counted in each, and the answer says so. -- **`store_usage`** — the store's total size; the largest repositories; the bytes in blobs that more +- **`artifact_store_usage`** — the store's total size; the largest repositories; the bytes in blobs that more than one repository marks; and the bytes in blobs no manifest marks, which is what the nightly collector frees next. -- **`store_references`** — for every manifest, one state (below), counted and sized by repository, and +- **`artifact_store_references`** — for every manifest, one state (below), counted and sized by repository, and listed when one repository is asked about. Then what the records keep that the store does not hold. -- **`store_collect`** — the dry run: what the controller would let go of, and how many bytes the nightly +- **`artifact_store_collect`** — the dry run: what the controller would let go of, and how many bytes the nightly collector would free once those are gone. A real run with `dry_run` false and a `why` asks the controller's `collect`, and answers what it did. @@ -80,6 +82,7 @@ the same mark, so their numbers are the collector's. | kept — recent build | one of the five most recent builds of a module the mesh holds | no | | holder of a kept archive | the manifest that keeps a kept archive's blob | no | | eligible | the mesh made it and keeps it for no reason | yes, through the controller | +| let go of, yet present | the controller recorded letting it go, and the store still holds it | no — said, for a person to look at | | holder of an eligible archive | the manifest that keeps an eligible archive's blob | yes, with its archive | | named document | a manifest the controller keeps under a tag (to-be 45 §9) | no | | unrecorded | no record names it | no — counted and sized only |