Skip to content

Changes for 0.6.0#193

Merged
Idleness76 merged 2 commits into
mainfrom
staging
May 11, 2026
Merged

Changes for 0.6.0#193
Idleness76 merged 2 commits into
mainfrom
staging

Conversation

@Idleness76
Copy link
Copy Markdown
Owner

Description

Implements two upstream feedback items (WG-006 and WG-007) as Weavegraph 0.6.0.

WG-006 — Invocation-scoped state lifecycle + normalization profiles
Adds a StateLifecycle annotation to StateKey<T> so callers can declare which slots are per-invocation scratch versus durable. NodePartial::clear_typed_extra_key / clear_extra_keys delete those slots via MapMerge's new JSON Merge Patch (RFC 7396) semantics. StateNormalizeProfile lets replay assertions ignore volatile keys without touching event comparison logic.

WG-007 — Runtime observability hooks + metrics adapter
Adds a RuntimeObserver trait with six lifecycle hook methods (invocation start/finish, node finish, checkpoint load/save, event bus emit). An observer is attached via AppRunnerBuilder::observer(Arc<dyn RuntimeObserver>) with zero overhead when unset. Observer panics are caught and logged as warnings. A MetricsObserver implementation is provided under the metrics feature flag, emitting standard counters and histograms via the metrics crate facade.

Also fixes MapMerge to treat incoming null as a key deletion (RFC 7396), which is a prerequisite for the clear methods to work correctly, and marks five public error enums #[non_exhaustive] to allow future variants without breaking changes.

Related Issues

Closes #

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Changes Made

  • src/state.rsStateLifecycle enum; StateKey<T> gains lifecycle field + invocation_scoped() const builder + lifecycle() getter; manual PartialEq/Hash/Eq impls that exclude the lifecycle field
  • src/node.rsNodePartial::clear_extra_keys and clear_typed_extra_key methods
  • src/reducers/map_merge.rsMapMerge now treats incoming null as a key deletion (JSON Merge Patch / RFC 7396)
  • src/runtimes/observer.rs (new)RuntimeObserver trait, six metadata structs, two outcome enums (all #[non_exhaustive])
  • src/runtimes/metrics_observer.rs (new, metrics feature)MetricsObserver with 5 counters and 3 histograms
  • src/runtimes/runner.rsobserver field on AppRunner/AppRunnerBuilder; ObservingEmitter private struct; call_observer_hook with catch_unwind; hook callsites at invocation start/finish, node finish, checkpoint load/save, and event bus emit
  • src/runtimes/replay.rsStateNormalizeProfile, normalize_state_with, compare_final_state_with, compare_replay_runs_with_profile
  • src/runtimes/mod.rspub mod observer, pub mod metrics_observer (feature-gated), re-exports for all new public types
  • src/runtimes/checkpointer.rs#[non_exhaustive] on CheckpointerError
  • Cargo.toml — version 0.6.0; metrics = { version = "0.24", optional = true } dep; metrics = ["dep:metrics"] feature
  • CHANGELOG.md / docs/MIGRATION.md — 0.6.0 section with full API inventory and migration guidance

Testing

  • Existing tests pass (cargo test)
  • Added new tests for changes
  • Tested manually (describe how)

make lint (rustfmt + clippy --all-targets --all-features -D warnings) and make test (cargo-nextest + doctests) both pass cleanly: 337 integration/unit tests, 161 doctests, 0 failures.

The metrics feature was separately verified with cargo build --features metrics and cargo clippy --features metrics -- -D warnings.

Test environment:

  • Rust version: 1.90.0 (1159e78c4 2025-09-14)
  • OS: Linux 6.8.0-111-generic

Checklist

  • My code follows the project's code style (cargo fmt)
  • I have run clippy and addressed warnings (cargo clippy)
  • I have updated documentation (if needed)
  • I have added tests that prove my fix/feature works
  • All tests pass locally
  • I have updated CHANGELOG.md (if user-facing change)
  • I have checked that no breaking changes are introduced (or documented them)

Breaking Changes

MapMerge null-deletion (RFC 7396): MapMerge previously stored serde_json::Value::Null verbatim in VersionedState.extra. It now removes the key when the incoming value is null. Any code that deliberately stored Value::Null as a meaningful state value must switch to an explicit sentinel (e.g. {"absent": true}). This change is required for clear_extra_keys / clear_typed_extra_key to function correctly.

#[non_exhaustive] error enums: RunnerError, NodeError, CheckpointerError, StateSlotError, and ReplayConformanceError are now #[non_exhaustive]. Exhaustive match expressions on these types must add a _ wildcard arm. See docs/MIGRATION.md for the exact before/after pattern.

Additional Notes

The RuntimeObserver trait is always compiled (no feature gate) so downstream crates can implement it without opting into any feature. The metrics feature only gates the ready-made MetricsObserver impl and the metrics crate dependency.

session_id and other high-cardinality fields are intentionally excluded from metric labels in MetricsObserver to avoid unbounded label cardinality in long-running services.

@Idleness76 Idleness76 self-assigned this May 11, 2026
@Idleness76 Idleness76 added documentation Improvements or additions to documentation enhancement New feature or request breaking-change Changes that break backward compatibility api-design Public API design and ergonomics labels May 11, 2026
@Idleness76 Idleness76 merged commit 84e7e2c into main May 11, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-design Public API design and ergonomics breaking-change Changes that break backward compatibility documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant