The review of tasks 01 to 15 goes in the implementer log, with the device check against the owner's Mattermost. Three follow-ups: - 16: the refusal without a runner says why. - 17: the texts that say who asked. - 18: approvals from non-approvers in direct or group messages go to an approver. Task 14's given serve_approvals.rs becomes serve_approvals.rs-task14, since task 18 hands over a new version. Tip T31 is added. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
97 lines
4.5 KiB
Markdown
97 lines
4.5 KiB
Markdown
# M4b task 14: the serve loop posts approvals and marks them
|
|
|
|
**Branch:** `m4b` (run `git switch m4b`; `git status --short` must be empty, otherwise stop)
|
|
**Commit subject:** `gatewayd: serve, posting approvals, marking them, and the listener`
|
|
|
|
## Goal
|
|
|
|
The serve loop does what `gateway.sock` connections ask (M4b spec, sections 6 and 8):
|
|
|
|
- **Show**: place the approval (its session's turn in flight: that thread; otherwise the first
|
|
approver's direct messages, as a new thread), post its parts in order, record the posts in the
|
|
state file, register it for answers (task 11), and reply with the post ids, or why it could not
|
|
be posted.
|
|
- **Ended**: forget it, and add how it ended to its last post, naming who answered.
|
|
- At the **first connection after a start**, the approval posts the last run left behind are
|
|
marked: their last post is replaced by its title and the restart line.
|
|
- `run` opens `gateway.sock` before connecting; a failure stops `gatewayd` at start
|
|
(`Stop::Start`, pointer `gatewayd-start-failed`).
|
|
|
|
## Files
|
|
|
|
- Copy: the skeleton `crates/gatewayd/src/serve/approvals.rs`,
|
|
`crates/gatewayd/tests/serve_approvals.rs`, `crates/gatewayd/tests/support/brokerd_client.rs`,
|
|
and a **new version** of the given `crates/gatewayd/tests/support/fake_mm.rs` (it gains post
|
|
edits, user names, and refusing posts)
|
|
- Modify: `crates/gatewayd/src/serve/mod.rs`, `docs/implementer-log.md`
|
|
|
|
## The skeleton
|
|
|
|
Written: `Open`, **`gateway_requests`** (drain the channel, never blocking) and **`show`** (read
|
|
both first). To fill, each with its steps in its comment: `place`, `ended`, `mark_left_behind`,
|
|
`mark`.
|
|
|
|
## `serve/mod.rs`, exactly
|
|
|
|
1. `mod approvals;` before `mod handle;`. Imports: `use std::collections::HashMap;`,
|
|
`use crate::approvals::Registry;`, `use crate::gateway::{self, ToLoop};`.
|
|
2. Three fields at the end of `struct Gateway`:
|
|
|
|
```rust
|
|
/// The approvals posted here, shared with the turns (for the notice) and judged by commands.
|
|
registry: Arc<Registry>,
|
|
/// What `gateway.sock` connections ask of the loop.
|
|
gateway_rx: Receiver<ToLoop>,
|
|
/// The last post of each approval posted here and not yet ended.
|
|
open: HashMap<u64, approvals::Open>,
|
|
```
|
|
|
|
3. `Gateway::new` gains a last parameter `gateway_rx: Receiver<ToLoop>`, and sets
|
|
`registry: Arc::new(Registry::new()), gateway_rx, open: HashMap::new(),`.
|
|
4. In `run`, right before `let client = Arc::new(Client::new(…));`:
|
|
|
|
```rust
|
|
let listener = match gateway::listen(&config.gateway_socket()) {
|
|
Ok(listener) => listener,
|
|
Err(why) => return Stop::Start(why),
|
|
};
|
|
let (gateway_tx, gateway_rx) = mpsc::channel();
|
|
if let Err(e) = gateway::serve(
|
|
listener,
|
|
gateway_tx,
|
|
gateway::Timing::default(),
|
|
Arc::clone(&log),
|
|
) {
|
|
return Stop::Start(format!("cannot start the gateway.sock thread: {e}"));
|
|
}
|
|
```
|
|
|
|
and `Gateway::new(config, client, state, log)` becomes
|
|
`Gateway::new(config, client, state, log, gateway_rx)`.
|
|
5. In `connected`, inside `if !self.restarted { … }`, after the `take_in_flight` loop:
|
|
`self.mark_left_behind()?;`
|
|
6. In `event_loop`, after `self.finished()?;`: `self.gateway_requests()?;`
|
|
|
|
## Steps
|
|
|
|
- [ ] **1. Copy.** `git switch m4b`, then
|
|
`cp docs/plans/M4b/files/crates/gatewayd/src/serve/approvals.rs crates/gatewayd/src/serve/ && cp docs/plans/M4b/files/crates/gatewayd/tests/serve_approvals.rs-task14 crates/gatewayd/tests/serve_approvals.rs && cp docs/plans/M4b/files/crates/gatewayd/tests/support/brokerd_client.rs docs/plans/M4b/files/crates/gatewayd/tests/support/fake_mm.rs crates/gatewayd/tests/support/`
|
|
- [ ] **2. Make the six `serve/mod.rs` changes.** `cargo build -p gatewayd` must succeed.
|
|
- [ ] **3. See it fail.** `cargo test -p gatewayd --test serve_approvals`. Expected: 4 fail, 1
|
|
passes (the socket is there while `gatewayd` runs).
|
|
- [ ] **4. Fill `mark`, `place`, `ended`, `mark_left_behind`**, `cargo check -p gatewayd` after
|
|
each.
|
|
- [ ] **5. See it pass.** `cargo test -p gatewayd --test serve_approvals`, three times: 5 passed.
|
|
Then `cargo test -p gatewayd`: every suite passes.
|
|
- [ ] **6. Run the gate.** `cargo fmt --all`, then `make gate`. Expected last line: `gate: ok`.
|
|
- [ ] **7. Log and commit.** `git add crates/gatewayd docs/implementer-log.md Cargo.lock && git commit`
|
|
|
|
## Done when
|
|
|
|
- `cargo test -p gatewayd` passes; `make gate` prints `gate: ok`.
|
|
|
|
## Stop and report if
|
|
|
|
- A comment above a `todo!()` does not fit its function, or contradicts a test: quote it.
|
|
- `show` or `gateway_requests` seems to need a change: they are given.
|