ISiteProjection Pennington.Pipeline
Single shared corpus projection: walks every indexable route once, captures its post-pipeline HTML once, parses the DOM once, and yields a stream of RenderedPage records. Every site-wide aggregator (search index, llms.txt, build-time link audit) folds over this stream instead of independently fanning out across the corpus.
this projection is for build-time and artifact-service consumers only. Materialization triggers parallel HTTP self-fetches that re-enter the request pipeline, so no component that runs during a content page's render or response processing may await it — that is the task-cycle deadlock from commit b719d73. The implementation fails fast instead of hanging: every projection-issued fetch is stamped via Infrastructure.CorpusFetchScope, and consuming the projection from such a request (or from inside its own materialization) throws a descriptive InvalidOperationException. Artifact services may consume it freely — their claimed URLs are disjoint from the page corpus the projection fetches. Request-path link verification stays on Infrastructure.PageLinkVerifier, which consults IContentService.DiscoverAllAsync and artifact claims only.
Methods
GetPageAsync
#public Task<RenderedPage> GetPageAsync(UrlPath canonicalPath, CancellationToken cancellationToken = default)
Returns the projected page at canonicalPath, or null when no page matches. Triggers full materialization on first call; cheap on subsequent calls.
Parameters
canonicalPathUrlPathcancellationTokenCancellationToken
Returns
Task<RenderedPage>GetPagesAsync
#public IAsyncEnumerable<RenderedPage> GetPagesAsync(CancellationToken cancellationToken = default)
Yields every renderable page in deterministic discovery order. Materializes lazily on first enumeration; subsequent calls replay the cached array until the instance is dropped by file-watch invalidation.
Parameters
cancellationTokenCancellationToken
Returns
IAsyncEnumerable<RenderedPage>Pennington.Pipeline.ISiteProjection
namespace Pennington.Pipeline;
/// Single shared corpus projection: walks every indexable route once, captures its post-pipeline HTML once, parses the DOM once, and yields a stream of RenderedPage records. Every site-wide aggregator (search index, llms.txt, build-time link audit) folds over this stream instead of independently fanning out across the corpus. this projection is for build-time and artifact-service consumers only. Materialization triggers parallel HTTP self-fetches that re-enter the request pipeline, so no component that runs during a content page's render or response processing may await it — that is the task-cycle deadlock from commit b719d73. The implementation fails fast instead of hanging: every projection-issued fetch is stamped via Infrastructure.CorpusFetchScope, and consuming the projection from such a request (or from inside its own materialization) throws a descriptive InvalidOperationException. Artifact services may consume it freely — their claimed URLs are disjoint from the page corpus the projection fetches. Request-path link verification stays on Infrastructure.PageLinkVerifier, which consults IContentService.DiscoverAllAsync and artifact claims only.
public interface ISiteProjection
{
/// Returns the projected page at canonicalPath, or null when no page matches. Triggers full materialization on first call; cheap on subsequent calls.
public Task<RenderedPage> GetPageAsync(UrlPath canonicalPath, CancellationToken cancellationToken = default)
;
/// Yields every renderable page in deterministic discovery order. Materializes lazily on first enumeration; subsequent calls replay the cached array until the instance is dropped by file-watch invalidation.
public IAsyncEnumerable<RenderedPage> GetPagesAsync(CancellationToken cancellationToken = default)
;
}