Documentation
¶
Overview ¶
Package resolve maps user-facing dataset refs to a (ReadCloser, Schema) pair. Four ref forms are supported:
- cohort.pulse local OsFs path
- archive.pulse#shard.pulse anchor inside a Pulse shard archive
- gs://bucket/path.pulse GCS-backed file (PUNT in v1: returns PRISM_RESOLVE_GCS_UNAVAILABLE)
- cohort:<id> registry lookup; the resolved string is recursively resolved (one level)
Every read goes through an afero.Fs so tests can use NewMemMapFs. The Resolver does not cache; it leaves caching to the DAG executor via Table.Hash() + per-node fingerprint.
GCS is intentionally not wired in P02. Pulse 0.8.4 does not ship a generic GCS afero.Fs; adding a real GCS SDK in this phase violates the dep-parity rule and inflates v1 scope. See D027.
Index ¶
Constants ¶
const EnvDatasetVar = "PRISM_DATASETS"
EnvDatasetVar is the env var consulted by LoadDatasetRegistryEnv.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type DataResolver ¶
DataResolver maps an opaque runtime reference to an inline dataset. Used to support the `data: {ref: "<name>"}` spec variant: the spec describes *what to draw*; the resolver provides *the data to draw it with*. Different environments resolve the same ref differently:
- A browser environment looks up an injected dataset from the page runtime via prism.setDataResolver.
- A server environment reads a pre-positioned file or queries a trusted backend.
- A test environment returns canned rows from a fixture map.
Implementations should be safe for concurrent use — the executor may call Resolve from multiple goroutines when several layers reference the same ref.
func ChainDataResolvers ¶
func ChainDataResolvers(resolvers ...DataResolver) DataResolver
ChainDataResolvers walks each resolver in order, returning the first non-unresolved result. Errors that are *not* ErrDataRefUnresolved short-circuit immediately. Nil resolvers in the chain are skipped silently.
type DataResolverFunc ¶
DataResolverFunc adapts a function to the DataResolver interface.
func (DataResolverFunc) ResolveData ¶
ResolveData implements DataResolver.
type Dataset ¶
Dataset is the in-memory dataset shape returned by a DataResolver. It carries row values + optional field schema, matching the inline `data: {values: [...]}` variant of the spec.
type DatasetLister ¶
type DatasetLister interface {
Names() []string
}
DatasetLister is an optional interface implementations may provide to enumerate the registered aliases. The Twirp `ListDatasets` RPC (P14) introspects registries by type-asserting to this interface; registries without a meaningful enumeration return nil and the RPC emits an empty list. Names returned are deduplicated across chained layers and sorted ascending.
type DatasetRegistry ¶
type DatasetRegistry interface {
// Resolve returns the backing ref for alias (path, anchor, gs://,
// or cohort:<id>). The second return is false when the alias is
// not registered.
Resolve(alias string) (string, bool)
}
DatasetRegistry resolves spec-level dataset aliases (`{"data": {"name": "current"}}`) to backing refs the resolver understands (paths, archive#shard anchors, gs:// urls, cohort:<id>). The registry is distinct from the cohort-id Registry above: cohort-ids are an internal indirection layer; dataset aliases are user-facing names declared in server config or the spec's `datasets` block.
D008 documents the combined client + server registry strategy. P07's loader handles the server-side half (JSON file + env var); the browser-side `<prism-dataset>` mirror lands in P12.
func ChainDatasetRegistries ¶
func ChainDatasetRegistries(layers ...DatasetRegistry) DatasetRegistry
ChainDatasetRegistries walks the supplied registries in order and returns the first hit per alias. Layers are tried left-to-right, so callers pass the highest-priority registry first. Nil entries are skipped.
func LoadDatasetRegistryEnv ¶
func LoadDatasetRegistryEnv() DatasetRegistry
LoadDatasetRegistryEnv parses comma-separated `name=path` pairs from PRISM_DATASETS. Malformed entries (missing `=`, empty name, empty path) are silently dropped — callers can post-validate via `len(registry)` if they want to surface a config error.
func LoadDatasetRegistryFile ¶
func LoadDatasetRegistryFile(path string, fs afero.Fs) (DatasetRegistry, error)
LoadDatasetRegistryFile parses a JSON file of shape
{"datasets": {"current": "cohorts/q1.pulse",
"prior": "cohorts/q4.pulse"}}
into a MapDatasetRegistry. YAML support is a documented TODO (D048): Pulse's go.mod does not ship a YAML loader and the dep-parity rule (Rule 13) forbids adding one in P07.
Returns an empty registry (not nil) when the file is absent so callers can chain it through ChainDatasetRegistries unconditionally.
type DefaultResolver ¶
type DefaultResolver struct {
// contains filtered or unexported fields
}
DefaultResolver is the production Resolver. It dispatches ref forms against the four known shapes and delegates to Pulse for the bulk of the work (single-file open, archive#shard anchor extraction).
Construction:
r := resolve.New(nil) // EmptyRegistry, no cohort:<id> lookups r := resolve.New(reg) // custom Registry
The fs argument to Resolve is taken per-call so callers can swap between OsFs, MemMapFs, or BasePathFs without rebuilding the resolver.
func New ¶
func New(reg Registry) *DefaultResolver
New constructs a DefaultResolver. Passing a nil registry yields an EmptyRegistry — every cohort:<id> ref will then return PRISM_RESOLVE_004.
type EmptyDatasetRegistry ¶
type EmptyDatasetRegistry struct{}
EmptyDatasetRegistry rejects every Resolve. Useful when callers want to declare "no registry" without a nil check at every site.
func (EmptyDatasetRegistry) Names ¶
func (EmptyDatasetRegistry) Names() []string
Names implements DatasetLister with the empty slice.
type EmptyRegistry ¶
type EmptyRegistry struct{}
EmptyRegistry rejects every lookup. Used when no registry is wired.
type ErrDataRefUnresolved ¶
type ErrDataRefUnresolved struct {
Ref string
}
ErrDataRefUnresolved signals that the caller's DataResolver could not satisfy the given ref. Plan / build surfaces it as PRISM_RESOLVE_REF_UNRESOLVED.
func (ErrDataRefUnresolved) Error ¶
func (e ErrDataRefUnresolved) Error() string
Error implements error.
type MapDataResolver ¶
MapDataResolver is a static map-backed resolver. Useful in tests and for embedding small canned datasets without writing a custom resolver. The zero value is a usable, empty resolver — Resolve returns ErrDataRefUnresolved for every ref.
func (MapDataResolver) ResolveData ¶
ResolveData implements DataResolver.
type MapDatasetRegistry ¶
MapDatasetRegistry is the trivial in-memory implementation. The zero value is an empty registry; construction is `MapDatasetRegistry{...}` or `LoadDatasetRegistryFile`.
func (MapDatasetRegistry) Names ¶
func (m MapDatasetRegistry) Names() []string
Names enumerates the alias keys for the in-memory registry. It returns a sorted, freshly-allocated slice (the caller may mutate the result without affecting the registry).
type MapRegistry ¶
MapRegistry is the default in-memory Registry. The zero value is an empty map; callers may also construct it via MapRegistry{"id": ref}.
type Registry ¶
Registry maps a cohort id (`cohort:<id>`) to its backing ref (path, anchor, or gs:// URL). The default in-process implementation is MapRegistry; the dashboard/orchestrator wires its own at runtime.
type Resolver ¶
type Resolver interface {
Resolve(ref string, fs afero.Fs) (io.ReadCloser, *encoding.Schema, error)
}
Resolver resolves a ref to a streaming reader plus the cohort's schema. The returned ReadCloser, when non-nil, owns its underlying file handle; callers must Close it. Schema is always non-nil on success.
Concrete implementations:
- DefaultResolver (resolve/default.go): the production path.
- tests may swap in a fake that returns canned bytes + schema.