Skip to content

feat(twap-monitor): PollOutcome lifecycle dispatch (BLEU-830)#7

Open
brunota20 wants to merge 2 commits into
feat/twap-monitor-retry-bleu-829from
feat/twap-monitor-lifecycle-bleu-830
Open

feat(twap-monitor): PollOutcome lifecycle dispatch (BLEU-830)#7
brunota20 wants to merge 2 commits into
feat/twap-monitor-retry-bleu-829from
feat/twap-monitor-lifecycle-bleu-830

Conversation

@brunota20

Copy link
Copy Markdown
Collaborator

Summary

After `poll_one`, the non-Ready arms now reach a typed lifecycle step:

Outcome WatchUpdate Effect
`TryNextBlock` `NoOp` re-poll next block
`TryOnBlock(n)` `SetNextBlock(n)` persist `next_block:{owner}:{params_hash}`
`TryAtEpoch(t)` `SetNextEpoch(t)` persist `next_epoch:{owner}:{params_hash}`
`DontTryAgain` `DropWatch` delete `watch:{owner}:{params_hash}` + best-effort delete of stale `next_block:` / `next_epoch:` gates

Decision is split out as the pure `outcome_to_update` returning a `WatchUpdate` enum; the impure `apply_watch_update` performs the local-store writes. That partition lets the four host-free tests assert the mapping exhaustively without wit-bindgen scaffolding.

`Ready` is mapped to `NoOp` as a safety net — `poll_all_watches` routes Ready to `submit_ready`, which owns the post-submit book-keeping. If a future refactor pipes Ready through the lifecycle path, the watch must NOT be erased.

Wire-format conventions (u64 LE, key shape `watch:{owner}:{params_hash}` + parallel `next_block:` / `next_epoch:`) stay the same as BLEU-827; no consumer changes required.

Stacks on #6 (BLEU-829 retry).

Linear: BLEU-830.

Test plan

  • `cargo test -p twap-monitor` — 34 host tests (3 BLEU-826 + 14 BLEU-827 + 7 BLEU-828 + 5 BLEU-829 + 5 BLEU-830: Ready / TryNextBlock / TryOnBlock / TryAtEpoch / DontTryAgain).
  • `cargo clippy --target wasm32-wasip2 -p twap-monitor -- -Dwarnings`.
  • `cargo clippy -p twap-monitor --tests -- -Dwarnings`.
  • `cargo build --target wasm32-wasip2 --release -p twap-monitor` — 300 KB .wasm.

After poll_one, the non-Ready arms now reach a typed lifecycle
step instead of dead-ending in the log:

- TryNextBlock  -> NoOp                — re-poll next block
- TryOnBlock(n) -> SetNextBlock(n)     -> persist next_block:{...}
- TryAtEpoch(t) -> SetNextEpoch(t)     -> persist next_epoch:{...}
- DontTryAgain  -> DropWatch           -> delete watch:{...} +
                                          best-effort delete of the
                                          stale next_block: /
                                          next_epoch: gates

The decision is split out as a pure `outcome_to_update` returning
a `WatchUpdate` enum, with the impure `apply_watch_update`
performing the local-store writes. That partition lets the four
host-free tests assert the mapping exhaustively without
wit-bindgen scaffolding.

`Ready` is deliberately mapped to `NoOp` here as a safety net —
poll_all_watches routes Ready to submit_ready, which owns the
post-submit book-keeping (submitted: marker + retry / drop). If
a future refactor accidentally pipes Ready through the lifecycle
path, the watch must NOT be erased.

Wire-format conventions (u64 LE bytes, key shape watch:{owner}:
{params_hash} and parallel next_block: / next_epoch:) stay the
same as BLEU-827; no consumer changes required.

Tests: 5 new (Ready, TryNextBlock, TryOnBlock, TryAtEpoch,
DontTryAgain). Total 34 host tests.

Linear: BLEU-830.
@linear-code

linear-code Bot commented Jun 15, 2026

Copy link
Copy Markdown

BLEU-830

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant