Checkpoint: concurrent IPC responsiveness fix

This commit is contained in:
Avi 2026-08-23 19:04:11 -05:00
commit ad70890efc

View file

@ -1,4 +1,4 @@
# Checkpoint — Profile rename + card-click selection + button wrap (2026-08-23) # Checkpoint — Responsive backend (concurrent IPC) + rename (2026-08-23)
**App renamed to Keynectr (2026-08-23).** A stopping point you can return to if this session is closed. Everything below was **App renamed to Keynectr (2026-08-23).** A stopping point you can return to if this session is closed. Everything below was
verified green at the moment this file was written. verified green at the moment this file was written.
@ -7,38 +7,57 @@ verified green at the moment this file was written.
- Project: `/home/avi/Projects/Nostr_Keynctr` (renamed from `0_Nostr` after commit `1116dfd`; - Project: `/home/avi/Projects/Nostr_Keynctr` (renamed from `0_Nostr` after commit `1116dfd`;
folder itself renamed from `Nostr-Keynectr` — see `2e4005d`) folder itself renamed from `Nostr-Keynectr` — see `2e4005d`)
- Git repo: `master` @ `d618a5a` ("Add profile rename with metadata republish (GUI + - Git repo: `master` @ `4d70b25` ("Make IPC concurrent so relay checks and feeds never
CLI)"). Before it: `64502c1` (button wrap), `653945a` (card-click selection), block the UI"). Before it: `d618a5a` (rename), `64502c1` (button wrap), `653945a`
`2e4005d` (folder-rename checkpoint), `24b34b6`, `6ead6f4`, `31ef305` (Keynectr (card-click selection), `2e4005d` (folder-rename checkpoint), `24b34b6`, `6ead6f4`,
rebrand), `a6329d5` (metadata publishing), `db81f8d` (delete + undo). `31ef305` (Keynectr rebrand), `a6329d5` (metadata publishing), `db81f8d`
(delete + undo).
- Working tree is **clean** apart from this checkpoint update, which is committed right after. - Working tree is **clean** apart from this checkpoint update, which is committed right after.
## What was completed ## What was completed
1. **Rename a profile (2026-08-23)** — new "Edit name" button on every Profiles card 1. **Backend made responsive (2026-08-23, `4d70b25`)** — user-visible lag fixed:
Selecting a profile took ~10 s and renaming ~30 s. Root causes: the IPC server
processed requests strictly one-at-a-time; the Home screen fires a relay test per
enabled relay on mount (a dead relay burns the full 8 s timeout each), and
`feed_get` held the shared lock during multi-second relay fetches — so Select queued
behind them; metadata publishing also waited 10 s for connections and sent to relays
one-by-one with 15 s timeouts each (~30 s with one dead relay).
Changes:
- IPC server now handles requests **concurrently** (task per request; replies are
id-correlated so out-of-order is fine). Mutations stay serialized via the shared
mutex, which moved from `std::sync` to `tokio::sync` (`App`, `Signer::connect`,
`run_sign_task`, CLI `signer connect`).
- `relay_test` and `feed_get` no longer hold the shared lock during network I/O
(they copy settings / active-npub under a short lock first).
- Metadata publish now sends to all relays **in parallel** with shorter timeouts
(connect 5 s, send 8 s) → worst case ~13 s instead of ~100 s; typical rename is a
few seconds.
2. **Rename a profile (2026-08-23)** — new "Edit name" button on every Profiles card
opens a modal (prefilled with the current name); saving stores the new label and opens a modal (prefilled with the current name); saving stores the new label and
republishes kind 0 metadata to enabled relays (`d618a5a`). Wired end-to-end: republishes kind 0 metadata to enabled relays (`d618a5a`). Wired end-to-end:
`profiles::rename_profile` (Rust), `rename_profile` IPC request, Electron `profiles::rename_profile` (Rust), `rename_profile` IPC request, Electron
RENDERER_METHODS allowlist, `api.renameProfile`, AppProvider `renameProfile`, RENDERER_METHODS allowlist, `api.renameProfile`, AppProvider `renameProfile`,
RenameModal UI, fake-backend support + test. CLI: `keynectr rename <npub> RenameModal UI, fake-backend support + test. CLI: `keynectr rename <npub>
<new-name>`. Empty names rejected; whitespace trimmed; works offline (change saved, <new-name>`. Empty names rejected; whitespace trimmed; works offline (change saved,
publish retried later via "Publish name"). publish retried later via "Publish name").
2. **Click anywhere on a profile card to select it (2026-08-23)** — on the Profiles 3. **Click anywhere on a profile card to select it (2026-08-23)** — on the Profiles
screen, clicking an inactive profile's card now does the same as pressing its screen, clicking an inactive profile's card now does the same as pressing its
"Select" button (`653945a`). Clicks on buttons inside the card (Copy / Publish name / "Select" button (`653945a`). Clicks on buttons inside the card (Copy / Publish name /
Picture / Edit name / Delete / Secret key / Select) do not trigger selection. The Picture / Edit name / Delete / Secret key / Select) do not trigger selection. The
active card is not clickable and shows a hover highlight on inactive cards. active card is not clickable and shows a hover highlight on inactive cards.
3. **Action buttons wrap on narrow windows (2026-08-23)** — `.profile-card-actions` now 4. **Action buttons wrap on narrow windows (2026-08-23)** — `.profile-card-actions` now
uses `flex-wrap: wrap`, so at half-screen width the action buttons wrap onto extra uses `flex-wrap: wrap`, so at half-screen width the action buttons wrap onto extra
rows inside the card instead of spilling past its border (`64502c1`). rows inside the card instead of spilling past its border (`64502c1`).
4. **Project folder renamed** to `Nostr_Keynctr` (`2e4005d`) — old path 5. **Project folder renamed** to `Nostr_Keynctr` (`2e4005d`) — old path
`Nostr-Keynectr` no longer exists; same project, new name. `Nostr-Keynectr` no longer exists; same project, new name.
5. Earlier in the session: Keynectr rebrand across UI/package/binary (`31ef305`, 6. Earlier in the session: Keynectr rebrand across UI/package/binary (`31ef305`,
`6ead6f4`, `24b34b6`), metadata/picture publishing (`a6329d5`) — see previous `6ead6f4`, `24b34b6`), metadata/picture publishing (`a6329d5`) — see previous
checkpoint notes below for details. checkpoint notes below for details.
## Commits added most recently ## Commits added most recently
- `4d70b25` Make IPC concurrent so relay checks and feeds never block the UI
- `d618a5a` Add profile rename with metadata republish (GUI + CLI) - `d618a5a` Add profile rename with metadata republish (GUI + CLI)
- `64502c1` Wrap profile card action buttons on narrow windows - `64502c1` Wrap profile card action buttons on narrow windows
- `653945a` Select a profile by clicking anywhere on its card - `653945a` Select a profile by clicking anywhere on its card
@ -51,7 +70,7 @@ Rust (repo root):
``` ```
cargo test # 99 passed; 0 failed cargo test # 99 passed; 0 failed
cargo clippy --all-targets # finishes; 2 pre-existing warnings in src/profiles.rs cargo clippy --all-targets # finishes; 2 pre-existing warnings in src/profiles.rs
# (drop of reference at :170 area, unused delete_profile) # (drop of reference, unused delete_profile)
cargo fmt --check # clean cargo fmt --check # clean
cargo build --release # success cargo build --release # success
``` ```
@ -96,6 +115,12 @@ $B rename <npub> <new-name> # rename + publish the new name
## Notes & next steps ## Notes & next steps
- **Architecture note (2026-08-23):** the shared `App` state mutex is now
`tokio::sync::Mutex` (`Arc<Mutex<App>>` in ipc.rs/signer.rs). Guards are held across
awaits by design; new handlers that touch vault/settings must lock it, while pure
network requests should copy inputs under a short lock and run lock-free.
- If rename/publish latency still feels long, next step would be background
publishing (return immediately, report via notice later) instead of shorter timeouts.
- Pre-existing clippy warnings in `src/profiles.rs` (drop of a reference, unused - Pre-existing clippy warnings in `src/profiles.rs` (drop of a reference, unused
`delete_profile`) are untouched — worth cleaning up in a future pass. `delete_profile`) are untouched — worth cleaning up in a future pass.
- Nostr has no relay-to-relay sync: names/pictures are only visible on relays they were - Nostr has no relay-to-relay sync: names/pictures are only visible on relays they were