Skip to content

Commit 80ccf04

Browse files
tizocdannywillems
authored andcommitted
docs(handover): Document into_dispatcher_and_state() too
1 parent 1ae9a84 commit 80ccf04

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

docs/handover/architecture-walkthrough.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ impl ComponentState {
122122

123123
// Phase 2: Dispatch follow-up actions
124124
let dispatcher = state_context.into_dispatcher();
125+
// Or use into_dispatcher_and_state() for global state access
126+
// let (dispatcher, global_state) = state_context.into_dispatcher_and_state();
125127
dispatcher.push(ComponentAction::NextAction { ... });
126128
}
127129
}

docs/handover/state-machine-development-guide.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,51 @@ The codebase uses callbacks for decoupled component communication. The `redux::c
239239

240240
For detailed callback patterns and examples, see [Architecture Walkthrough](architecture-walkthrough.md#callbacks-pattern).
241241

242+
### Global State Access Pattern
243+
244+
When reducers need to access multiple parts of the global state or coordinate between different subsystems, use `into_dispatcher_and_state()` instead of `into_dispatcher()`.
245+
246+
**When to use `into_dispatcher_and_state()`:**
247+
- Generating request IDs from other subsystems
248+
- Reading configuration from other state machines
249+
- Coordinating between multiple components
250+
- Accessing peer information or network state
251+
252+
**Common use cases:**
253+
```rust
254+
// Getting request IDs from other subsystems
255+
let (dispatcher, global_state) = state_context.into_dispatcher_and_state();
256+
let req_id = global_state.snark.user_command_verify.next_req_id();
257+
dispatcher.push(SnarkUserCommandVerifyAction::Init { req_id, ... });
258+
259+
// Accessing peer information for P2P operations
260+
let (dispatcher, global_state) = state_context.into_dispatcher_and_state();
261+
for peer_id in global_state.p2p.ready_peers() {
262+
dispatcher.push(TransactionPoolAction::P2pSend { peer_id });
263+
}
264+
265+
// Coordinating between multiple state machines
266+
let (dispatcher, global_state) = state_context.into_dispatcher_and_state();
267+
let best_tip = global_state.transition_frontier.best_tip()?;
268+
let cur_slot = global_state.cur_global_slot()?;
269+
// Use both pieces of information for decision making
270+
```
271+
272+
**Pattern structure:**
273+
```rust
274+
let (dispatcher, global_state) = state_context.into_dispatcher_and_state();
275+
// Read from global state
276+
let info = global_state.some_subsystem.get_info();
277+
// Dispatch actions using that information
278+
dispatcher.push(SomeAction::WithInfo { info });
279+
```
280+
281+
**Important notes:**
282+
- Only use when you need to read from global state
283+
- Prefer `into_dispatcher()` for simple action dispatching
284+
- The global state reference is read-only
285+
- Common in P2P, block producer, and transaction pool reducers
286+
242287
## Basic Debugging
243288

244289
For comprehensive debugging tools and troubleshooting, see [State Machine Debugging Guide](state-machine-debugging-guide.md).
@@ -272,6 +317,8 @@ pub enum YourAction {
272317
- [ ] Add `#[action_event(level = debug)]` for logging
273318
- [ ] Implement enabling condition in `EnablingCondition` trait
274319
- [ ] Add handler in reducer with proper state access pattern
320+
- Use `into_dispatcher()` for simple action dispatching
321+
- Use `into_dispatcher_and_state()` when needing global state access
275322
- [ ] Test enabling condition logic matches reducer expectations
276323
- [ ] Add documentation comment explaining the action's purpose
277324

docs/handover/state-machine-structure.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ The `Substate` system enforces the two-phase reducer pattern through its API des
225225

226226
1. **Phase 1 - State Updates**: `state_context.get_substate_mut()` provides mutable access to state
227227
2. **Phase 2 - Action Dispatching**: `state_context.into_dispatcher()` consumes the context and returns a dispatcher
228+
- Use `into_dispatcher()` for simple action dispatching
229+
- Use `into_dispatcher_and_state()` when you need read-only access to global state for coordination
228230

229231
This design makes it impossible to mix state updates and action dispatching:
230232
- Once you call `into_dispatcher()`, you can no longer access mutable state
@@ -238,6 +240,8 @@ state.field = new_value; // ✓ Allowed
238240

239241
// Phase 2: Action dispatching only
240242
let dispatcher = state_context.into_dispatcher();
243+
// Or for global state access:
244+
// let (dispatcher, global_state) = state_context.into_dispatcher_and_state();
241245
dispatcher.push(SomeAction { ... }); // ✓ Allowed
242246
// state.field = other_value; // ✗ Compiler error - state no longer accessible
243247
```

0 commit comments

Comments
 (0)