4.5 KiB
State Internals
The internal/state package owns filesystem-backed run state: safe path
derivation, metadata persistence, prior-report lookup, and read-only report
inspection. It does not decide which reports to generate or deliver. For the
operator-facing layout and retention procedures, see the
operations guide.
Store construction and artifact paths
NewFilesystemStore requires a workspace root and rejects absolute or
escaping values for every configured state directory. Paths then validates a
run ID and artifact group before deriving all paths from the report's valid
start date (YYYY-MM-DD). This keeps a run's artifacts together while making
the paths safe to use below the configured workspace.
| Artifact | Derived location |
|---|---|
| Module snapshot | snapshots/<group>/<date>/modules.<run-id>.json |
| Metadata | snapshots/<group>/<date>/metadata.<run-id>.json |
| Data package | data-packages/<group>/<date>/data_package.<run-id>.yaml |
| Render preflight | preflight/<group>/<date>/render.<run-id>.json |
| Notification record | notifications/<group>/<date>/distributor.<run-id>.json |
| Managed report | reports/<group>/<date>/report.<run-id>.md |
| Generated text | snapshots/<group>/<date>/generated_text.<run-id>.json |
| Generated-text source and result | snapshots/<group>/<date>/generated_text_raw.<run-id>.json and generated_text_result.<run-id>.json |
| Generated-text render context | snapshots/<group>/<date>/render_context.<run-id>.json |
The configured notification root separates notification artifacts from report artifacts; single-report notification paths use the report's valid date. Report producers create parent directories as needed and write the report body; state is responsible for the surrounding paths and saved run artifacts.
Batch Distributor notifications are derived separately as
notifications/batches/<batch>/<local-date>/distributor.<batch-run-id>.json.
Their date is calculated from the batch start in its configured location, and
the batch identity and run ID receive the same path-segment validation as
single-report artifact identifiers.
Metadata and durable writes
Metadata is the durable inventory for a run. It records its schema version,
run identity, generated and valid timestamps, artifact group and mode, source
content and provenance, and the module snapshot, data-package, preflight,
report, generated-artifact, and notification locations when present.
BuildMetadataFromBriefingMetadata establishes the common fields; the
application adds locations as artifacts are produced. SaveMetadata requires
the run ID and the module snapshot, data-package, preflight, and metadata
paths. The package also saves module snapshots, data packages, preflight
records, generated-text artifacts, render contexts, and notifications. JSON
writes use fileutil.WriteJSONAtomic, so readers do not observe a partially
written state file.
The data package itself follows the shared weather-data contract. Report text, templates, and external delivery payloads remain owned by their respective packages and integration references.
Prior reports and inspection
FindPriorSnapshot searches metadata rather than guessing from filenames. It
only considers an earlier compatible report in the same artifact group and
supports the comparison strategies defined by the report request:
same_valid_datefinds an earlier generated report for the same valid day.weekend_windowfinds a prior comparable weekend window.
The newest eligible metadata record wins; the current run is excluded. Unreadable or malformed candidate metadata is ignored so a damaged historical record does not block a new run.
ListReports walks saved metadata, returns results ordered newest-first by
generation time, and treats a missing snapshots directory as an empty history.
LoadMetadataByRunID builds on that inspection path. These APIs are read-only;
repairing or pruning stored state is an operational concern.
Boundaries and verification
The package rejects unsafe path components and incomplete metadata before writing. Callers must provide a valid report request, artifact group, and store configuration. Its focused tests cover path derivation, atomic persistence, metadata validation, comparison eligibility, and report listing:
go test ./internal/state
See application orchestration for the order in which these artifacts are created and report templates for the user-facing report contract.