CorpusFetchScope
Pennington.Infrastructure
Runtime tripwire for the b719d73 deadlock class: a single-flight corpus task (the site projection) awaited from work its own materialization spawned is a task-level circular wait that hangs forever. Two flags mark the dangerous regions so SiteProjection can throw a descriptive exception instead of deadlocking:
InsideCorpusFetch— this request IS a projection-issued page self-fetch.RenderedHtmlFetcherstampsHeaderNameon every fetch (anAsyncLocalalone would not cross the Kestrel loopback socket in dev), andUsePenningtonenters the scope when the header is present.InsideMaterialization— the projection's materialization is on the current async flow; re-entering it (e.g. from a content service's discovery) would await a task that is waiting on the caller.
Properties
InsideCorpusFetchbool- True while processing a request the projection issued to render a page.
InsideMaterializationbool- True while the projection's corpus materialization is on the current async flow.
Fields
HeaderNamestring- Default:
"X-Pennington-Corpus-Fetch"Header stamped on projection-issued self-fetches. Dev-only surface: a client sending it manually gets the fail-fast exception on any page whose render path consumes the projection — which is exactly the bug the exception describes.
Methods
EnterCorpusFetch
#public static IDisposable EnterCorpusFetch()
Marks the current async flow as a projection-issued page fetch until disposed.
Returns
IDisposableEnterMaterialization
#public static IDisposable EnterMaterialization()
Marks the current async flow as projection materialization until disposed.
Returns
IDisposablePennington.Infrastructure.CorpusFetchScope
namespace Pennington.Infrastructure;
/// Runtime tripwire for the b719d73 deadlock class: a single-flight corpus task (the site projection) awaited from work its own materialization spawned is a task-level circular wait that hangs forever. Two flags mark the dangerous regions so SiteProjection can throw a descriptive exception instead of deadlocking: InsideCorpusFetch — this request IS a projection-issued page self-fetch. RenderedHtmlFetcher stamps HeaderName on every fetch (an AsyncLocal alone would not cross the Kestrel loopback socket in dev), and UsePennington enters the scope when the header is present.InsideMaterialization — the projection's materialization is on the current async flow; re-entering it (e.g. from a content service's discovery) would await a task that is waiting on the caller.
public class CorpusFetchScope
{
/// Marks the current async flow as a projection-issued page fetch until disposed.
public static IDisposable EnterCorpusFetch()
;
/// Marks the current async flow as projection materialization until disposed.
public static IDisposable EnterMaterialization()
;
/// Header stamped on projection-issued self-fetches. Dev-only surface: a client sending it manually gets the fail-fast exception on any page whose render path consumes the projection — which is exactly the bug the exception describes.
public static const string HeaderName
;
/// True while processing a request the projection issued to render a page.
public static bool InsideCorpusFetch { get; }
/// True while the projection's corpus materialization is on the current async flow.
public static bool InsideMaterialization { get; }
}