Class RebuildPass
WalkConsumer - so N
metadata rebuilders never mean N tree walks. This is the walk half of the two-route derived-metadata contract
made runnable: a scheduled surface resolves the walk, gathers WalkConsumer.discovered() and calls
run(ArtifactWalk, ArtifactStore, List, List) on a cadence; steady-state freshness stays with the publication events
(PublicationObserver.onPublished / onDeleted), and this pass is the first-activation back-fill,
the periodic refresh and the self-heal - a consumer enabled late rebuilds its whole view from it.
What a consumer is handed. Every leaf under the walked roots that is a serving pointer - a small object
naming a lower-case SHA-256 - is delivered as one WalkConsumer.onRetained(ArtifactDescriptor, ArtifactStore) call with the descriptor
richness this neutral site has: under the free core's own publish/ namespace the descriptor's path is the
serving request path (exactly what onPublished / onDeleted carry); under any other pointer root
(a format's own blobs-namespace keys) the path is the raw store key, whose layout only the owning format knows -
a coordinate-needing consumer describes it through its format. The blob hash is always set; the size is the
stored blob's, or -1 for a pointer whose blob is missing - delivered, not skipped, so a reconcile
consumer sees exactly the torn state it exists to repair. A leaf that names no hash (a sidecar row, a marker, an
index) is never delivered.
The withheld screen. Under the free publish/ namespace the pass yields exactly what a GET
would, applying the same withheld screen PublishedAssets does through Publication.located: the
quarantine review subtree (publish/quarantine/...) is stored but never served, so it is never delivered
(no phantom index entry for a held pointer); and a path a screen retracts after the fact (a
PublishInterceptor.withheld verdict against an artifact that has served for months) is skipped, so a
rebuild never reinstates a retracted-after-advisory artifact into a consumer's index. A torn pointer whose blob is
merely gone is not withheld - it is still delivered as the torn state a reconcile consumer repairs, so
only a path whose blob is present yet unlocatable is screened out. The screen is the publish/ withhold
model's; a format's own blobs-namespace root carries no publication pointer and is delivered raw as before.
Delivery and failure. The walk's contract carries over: every retained pointer is delivered exactly
once per pass, and at least once for the uncommitted stride tail after a crash-resume - consumers are idempotent.
A consumer failure propagates and stops this worker's segment with its claim left to expire; the pass then
resumes from the last committed cursor, so a failure delays a rebuild but never silently truncates it - a stuck
pass is visible through ArtifactWalk.pass(ArtifactStore, String) / ArtifactWalk.segments(ArtifactStore, String), never a quietly-incomplete
view served as whole. WalkConsumer.onPassStarted(WalkPass) fires on this worker before its first delivery (and
before onPassCompleted on an empty store - a rebuild from an empty truth is still a rebuild);
WalkConsumer.onPassCompleted(WalkPass) fires when this worker observed the pass complete. The hooks are per-worker:
with one scheduled worker driving the pass - the default - a snapshot rebuilder sees the whole pass between its
hooks, while a deployment that fans run across threads or nodes keeps every streaming consumer correct
but must not drive a snapshot rebuilder this way (its accumulation would span workers) - the degrade-and-say-so
each such consumer records.
-
Field Summary
Fields -
Method Summary
Modifier and TypeMethodDescriptionrun(ArtifactWalk walk, build.jenesis.repository.store.ArtifactStore store, build.jenesis.repository.store.Publication publication, List<String> pointerRoots, List<WalkConsumer> consumers) The explicit seam: join the shared rebuild pass reusing aPublicationalready constructed over the same store rather than making a second, so the withheld screen over thepublish/namespace runs the caller's interceptor chain (the free edition'sServiceLoader-discovered chain is empty; a test or an embedder injects one here) - the same seamPublishedAssetsexposes for the same reason.run(ArtifactWalk walk, build.jenesis.repository.store.ArtifactStore store, List<String> pointerRoots, List<WalkConsumer> consumers) Join the shared rebuild pass overpointerRoots(the freepublishnamespace plus every blobs-namespace root the caller's installed formats declare) and stream every retained pointer to every one ofconsumers; empty when there is no consumer to feed - nothing is enumerated and no pass state is touched.
-
Field Details
-
CONSUMER
The pass-state scope every joiner shares (walks/rebuild/...) - one pass, however many workers.- See Also:
-
-
Method Details
-
run
public static Optional<WalkPass> run(ArtifactWalk walk, build.jenesis.repository.store.ArtifactStore store, List<String> pointerRoots, List<WalkConsumer> consumers) throws IOException Join the shared rebuild pass overpointerRoots(the freepublishnamespace plus every blobs-namespace root the caller's installed formats declare) and stream every retained pointer to every one ofconsumers; empty when there is no consumer to feed - nothing is enumerated and no pass state is touched. Returns the pass as this worker last saw it:COMPLETEwhen it just finished,ACTIVEwhile other holders still own segments - re-invoke on the next cadence, or let another node finish.- Throws:
IOException
-
run
public static Optional<WalkPass> run(ArtifactWalk walk, build.jenesis.repository.store.ArtifactStore store, build.jenesis.repository.store.Publication publication, List<String> pointerRoots, List<WalkConsumer> consumers) throws IOException The explicit seam: join the shared rebuild pass reusing aPublicationalready constructed over the same store rather than making a second, so the withheld screen over thepublish/namespace runs the caller's interceptor chain (the free edition'sServiceLoader-discovered chain is empty; a test or an embedder injects one here) - the same seamPublishedAssetsexposes for the same reason.- Throws:
IOException
-