| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Ecluse.Core.Server.Metadata
Description
Wiring a per-request Ecluse.Core.Registry.Metadata.MetadataClient for the serve path: the cross-cutting caching, metrics, and failure-logging policy wrapped around a registry's raw fetch primitive.
The read boundary's type lives in the registry layer (agnostic); a registry's raw fetch primitive lives with that registry (npm's in Ecluse.Core.Registry.Npm.Metadata). What lives here is the serve-path policy that is the same regardless of ecosystem: whether an origin is resolved through the shared metadata cache, recording the upstream-fetch metrics, and logging a failure once in the request's context. Keeping that policy in the serve layer is what lets the registry layer stay free of the cache and telemetry.
The two operations differ in how they resolve. The full-manifest op resolves the whole
packument through the shared full-packument cache. The single-version op takes a
hybrid path so a cold tarball gate need not pay a whole-packument decode to consult
one version (see newMetadataClient): it consults a small (package, version) cache, then
the warm full-packument cache read-only (so a packument GET followed by its tarball
gate still collapses to one upstream call), and only on a cold miss leads its own
selective fetch -- parsing just the requested version out of the full bytes -- into the
(package, version) cache, never writing the whole packument back to the shared cache.
Synopsis
- data ManifestCaching
- newMetadataClient :: MetricsPort -> Upstream -> ManifestCaching -> (PackageName -> MetadataError -> IO ()) -> (PackageName -> [InvalidEntry] -> IO ()) -> (PackageName -> IO ()) -> (PackageName -> IO (Either MetadataError Manifest)) -> (PackageName -> Version -> IO (Either MetadataError (Maybe PackageDetails))) -> MetadataClient
- newNpmMetadataClient :: TracingPort -> MetricsPort -> Upstream -> ManifestCaching -> (PackageName -> MetadataError -> IO ()) -> (PackageName -> [InvalidEntry] -> IO ()) -> (PackageName -> IO ()) -> NpmClientConfig -> MetadataClient
Caching policy
data ManifestCaching Source #
How a read handle resolves the full manifest for one origin.
The two origins of a packument merge differ exactly here: the private origin is the per-client authority and must not be shared, while the public origin is anonymous and shared across every client.
Constructors
| Uncached | Resolve directly, uncached -- the per-client private origin, re-fetched every request so the upstream re-authorises each client's own forwarded credential. |
| Cached MetadataCache Source | Resolve through the shared metadata cache under the origin's |
Constructing a per-request read handle
newMetadataClient :: MetricsPort -> Upstream -> ManifestCaching -> (PackageName -> MetadataError -> IO ()) -> (PackageName -> [InvalidEntry] -> IO ()) -> (PackageName -> IO ()) -> (PackageName -> IO (Either MetadataError Manifest)) -> (PackageName -> Version -> IO (Either MetadataError (Maybe PackageDetails))) -> MetadataClient Source #
Build a per-request read handle from a registry's raw fetch primitives -- one that fetches and projects the full manifest, one that fetches and selectively projects a single version -- wiring them with the caching policy, the upstream-fetch metrics, and a request-context failure log.
The full-manifest op resolves the whole packument through the shared full-packument cache. The single-version op takes the hybrid path that delivers the cheap cold tarball gate while preserving the warm install one-call property:
- consult the small
(package, version)cache -- a hit (a positive snapshot, or a cached determined absence) returns at once; - else consult the warm full-packument cache read-only -- a hit selects the one version
from the shared entry (so a packument
GETfollowed by its tarball gate is still one upstream call), and does not populate the version cache; - else (cold) lead the raw single-version fetch -- which fetches the full bytes but
parses only the requested version -- through the
(package, version)cache's single-flight, caching the resulting snapshot (or its determined absence) there, and never writing the whole packument back to the shared cache.
For the Uncached policy (the per-client private origin) there is no shared cache to
consult, so the single-version op is the raw selective fetch, uncached, re-run each request.
The failure log is invoked once per real fetch (inside the cache's single-flight
leader), in the caller's logging context, so a coalesced follower never re-logs a
failure the leader already reported. The dropped-entry log (logInvalid) is invoked the
same way (once per real full-manifest fetch, only when the projection dropped a
malformed entry), so an operator sees a degraded-but-served document without it
re-logging on every cache hit.
newNpmMetadataClient :: TracingPort -> MetricsPort -> Upstream -> ManifestCaching -> (PackageName -> MetadataError -> IO ()) -> (PackageName -> [InvalidEntry] -> IO ()) -> (PackageName -> IO ()) -> NpmClientConfig -> MetadataClient Source #
Build a per-request read handle for the npm protocol over one origin's fetch
configuration: the npm full-manifest and single-version fetches as the raw primitives, with
the serve-path caching, metrics, and the failure and dropped-entry logs wired by
newMetadataClient.