chore: refactor the backend #17
@@ -160,15 +160,15 @@ impl Backend {
|
||||
|
||||
let task = cx.background_spawn(async move {
|
||||
for url in BOOTSTRAP_RELAYS {
|
||||
client.add_relay(url).await?;
|
||||
client.add_relay(url).and_connect().await?;
|
||||
}
|
||||
for url in INDEXER_RELAYS {
|
||||
client
|
||||
.add_relay(url)
|
||||
.capabilities(RelayCapabilities::DISCOVERY)
|
||||
.and_connect()
|
||||
.await?;
|
||||
}
|
||||
client.connect().await;
|
||||
Ok::<(), Error>(())
|
||||
});
|
||||
|
||||
@@ -425,6 +425,7 @@ impl Backend {
|
||||
let path = cache.repo_path(&addr);
|
||||
let owner = public_key.to_bech32().unwrap();
|
||||
let servers = grasp_servers.clone();
|
||||
let client = self.client.clone();
|
||||
|
||||
cx.spawn(async move |this, cx| {
|
||||
// Initialize the local clone and create the user's working copy from it.
|
||||
@@ -488,10 +489,9 @@ impl Backend {
|
||||
let commit_sha = Sha1Hash::from_str(&commit).map_err(|_| anyhow!("invalid id"))?;
|
||||
|
||||
// The nostr client queues events until each relay is connected.
|
||||
this.update(cx, |this, cx| {
|
||||
let urls: Vec<String> = servers.iter().map(ToString::to_string).collect();
|
||||
this.add_relays(urls, cx);
|
||||
})?;
|
||||
for url in &servers {
|
||||
client.add_relay(url).and_connect().await.ok();
|
||||
}
|
||||
|
||||
// The state event is the push authorization. It must be accepted before the push below.
|
||||
let announcement = GitRepositoryAnnouncement {
|
||||
@@ -622,6 +622,7 @@ impl Backend {
|
||||
|
||||
let owner = public_key.to_bech32().unwrap();
|
||||
let servers = grasp_servers.clone();
|
||||
let client = self.client.clone();
|
||||
|
||||
cx.spawn(async move |this, cx| {
|
||||
let work = cx.background_spawn({
|
||||
@@ -635,10 +636,9 @@ impl Backend {
|
||||
let (state, euc) = work.await?;
|
||||
|
||||
// The nostr client queues events until each relay is connected.
|
||||
this.update(cx, |this, cx| {
|
||||
let urls: Vec<String> = servers.iter().map(ToString::to_string).collect();
|
||||
this.add_relays(urls, cx);
|
||||
})?;
|
||||
for url in &servers {
|
||||
client.add_relay(url).and_connect().await.ok();
|
||||
}
|
||||
|
||||
// The state event is the push authorization. It must be accepted before the push below.
|
||||
let announcement = GitRepositoryAnnouncement {
|
||||
@@ -1045,22 +1045,22 @@ impl Backend {
|
||||
task.detach();
|
||||
}
|
||||
|
||||
/// Fetch the user's grasp list and add the listed grasp servers as relays.
|
||||
/// Sync the user's grasp list and add the listed grasp servers as relays.
|
||||
fn bootstrap_user(&mut self, public_key: PublicKey, cx: &mut Context<Self>) {
|
||||
let client = self.client.clone();
|
||||
|
||||
let task: Task<Result<(), Error>> = cx.spawn(async move |this, cx| {
|
||||
let result = async {
|
||||
let events: Vec<Event> = client
|
||||
.fetch_events(filters::grasp_list(public_key))
|
||||
.await?
|
||||
.into_iter()
|
||||
.collect();
|
||||
sync_bootstrap_only(
|
||||
&client,
|
||||
filters::grasp_list(public_key),
|
||||
SyncOptions::default(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
for url in latest_grasp_list_servers(events) {
|
||||
client.add_relay(url.as_str()).await.ok();
|
||||
for url in user_grasp_list_servers(client.clone(), public_key).await? {
|
||||
client.add_relay(url).and_connect().await.ok();
|
||||
}
|
||||
client.connect().await;
|
||||
|
||||
Ok::<_, Error>(())
|
||||
}
|
||||
@@ -1137,32 +1137,6 @@ impl Backend {
|
||||
task.detach();
|
||||
}
|
||||
|
||||
/// Add relays and connect to them.
|
||||
pub fn add_relays(&mut self, urls: Vec<String>, cx: &mut Context<Self>) {
|
||||
let client = self.client.clone();
|
||||
|
||||
let task = cx.background_spawn(async move {
|
||||
for url in urls {
|
||||
client.add_relay(&url).await?;
|
||||
}
|
||||
client.connect().await;
|
||||
Ok::<(), Error>(())
|
||||
});
|
||||
|
||||
let notify_task: Task<Result<(), Error>> = cx.spawn(async move |this, cx| {
|
||||
match task.await {
|
||||
Ok(()) => {
|
||||
this.update(cx, |_this, cx| cx.notify())?;
|
||||
}
|
||||
Err(e) => {
|
||||
this.update(cx, |_this, cx| cx.emit(BackendEvent::error(e.to_string())))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
notify_task.detach();
|
||||
}
|
||||
|
||||
/// Connect to a repository's announced relays, its NIP-34 `relays` tag.
|
||||
///
|
||||
/// Callers are responsible for not repeating this for relays they already
|
||||
@@ -1396,8 +1370,7 @@ async fn connect_repo_relays(
|
||||
|
||||
// Ensure relay connections
|
||||
for url in relays.iter() {
|
||||
client.add_relay(url).await?;
|
||||
client.connect_relay(url).await?;
|
||||
client.add_relay(url).and_connect().await?;
|
||||
}
|
||||
|
||||
// Run neg sync for each filter
|
||||
@@ -1724,9 +1697,9 @@ async fn stage_event_on_relay(
|
||||
) -> Result<(), String> {
|
||||
client
|
||||
.add_relay(relay)
|
||||
.and_connect()
|
||||
.await
|
||||
.map_err(|e| format!("could not add relay {relay}: {e}"))?;
|
||||
client.connect().await;
|
||||
|
||||
let output = client
|
||||
.send_event(event)
|
||||
|
||||
@@ -30,6 +30,17 @@ Each is addressed below with concrete file:line references and a verified replac
|
||||
|
||||
## 1. `fetch_events` — one call site, and it should go too
|
||||
|
||||
> **Status: done.** `bootstrap_user` now calls `sync_bootstrap_only` (the
|
||||
> same helper `Backend::sync_bootstrap` already used) against
|
||||
> `filters::grasp_list(public_key)`, then reads the result back out through
|
||||
> the existing `user_grasp_list_servers` query helper instead of hand-rolling
|
||||
> a second `BTreeSet<Event>` → `Vec<Event>` collect. `client.add_relay(url)`
|
||||
> no longer round-trips through `.as_str()`, and connects with
|
||||
> `.and_connect()` (see §8) instead of a trailing pool-wide `client.connect()`.
|
||||
> `grep -rn "fetch_events" crates/` now returns nothing in the whole
|
||||
> workspace. `cargo check --workspace`, `cargo clippy -p signed_state`, and
|
||||
> `cargo test -p signed_state` (24 tests, unchanged) all pass.
|
||||
|
||||
```
|
||||
grep -rn "fetch_events" crates/
|
||||
crates/signed_state/src/backend.rs:1065
|
||||
@@ -574,6 +585,26 @@ to `RepoListStore`.
|
||||
|
||||
## 8. Relay add/connect: stop round-tripping through strings, stop reconnecting the whole pool
|
||||
|
||||
> **Status: done.** Every `add_relay` call site now passes the `RelayUrl`
|
||||
> directly (no `.as_str()`/`ToString` round trip) and chains `.and_connect()`
|
||||
> instead of a separate, pool-wide `client.connect()`/`client.connect_relay()`
|
||||
> call: `Backend::bootstrap` (both the `BOOTSTRAP_RELAYS` and `INDEXER_RELAYS`
|
||||
> loops), `bootstrap_user`, `create_repository`, `publish_local_repo`,
|
||||
> `connect_repo_relays`, and `stage_event_on_relay`. `Backend::add_relays` is
|
||||
> deleted entirely — its two callers (`create_repository`, `publish_local_repo`)
|
||||
> now capture `client` once before the surrounding `cx.spawn` and loop
|
||||
> `client.add_relay(url).and_connect().await.ok();` directly over the
|
||||
> `Vec<RelayUrl>` they already had, with no `Vec<String>` conversion at all.
|
||||
> Verified `.and_connect()` (`client/api/add.rs`) and pool-wide `.connect()`
|
||||
> semantics (`client/api/connect.rs`) against the pinned nostr-sdk source
|
||||
> before making the change (see chat history), plus that `pool.sync()`
|
||||
> requires relays to already be present in the pool
|
||||
> (`pool/mod.rs:679-693`, `relays.get(&url).ok_or_else(...)`), which is why
|
||||
> `sync_bootstrap_only`/`bootstrap_user` can safely assume `BOOTSTRAP_RELAYS`
|
||||
> are already added by `Backend::bootstrap` before any sync runs.
|
||||
> `cargo check --workspace`, `cargo clippy -p signed_state`, and
|
||||
> `cargo test -p signed_state` (24 tests) all pass.
|
||||
|
||||
Flagged example (`backend.rs:1071-1074`):
|
||||
|
||||
```rust
|
||||
@@ -1257,14 +1288,18 @@ method.
|
||||
bug in `RepoDetailView`/`NewPullRequestView` along the way.
|
||||
|
||||
Done: both halves are complete, see §6 and §14 for details.
|
||||
3. **Fix the relay add/connect calls** (§8): drop `.as_str()`/`ToString`
|
||||
3. ✅ **Fix the relay add/connect calls** (§8): drop `.as_str()`/`ToString`
|
||||
round trips, replace `add_relay` + blanket `client.connect()`/
|
||||
`connect_relay` pairs with `add_relay(url).and_connect()`, and delete
|
||||
`Backend::add_relays`. Mechanical, no behavior change beyond "connect
|
||||
only what was just added."
|
||||
4. **Fix `bootstrap_user`** to sync+query instead of `fetch_events` (§1).
|
||||
|
||||
Done: see §8 for the full list of call sites and verification notes.
|
||||
4. ✅ **Fix `bootstrap_user`** to sync+query instead of `fetch_events` (§1).
|
||||
One function, fully covered by existing tests for
|
||||
`latest_grasp_list_servers`.
|
||||
|
||||
Done: see §1. `fetch_events` no longer appears anywhere in the workspace.
|
||||
5. **Generalize the 3 `signed_git` URL-list signatures** to `&[impl AsRef<str>]`
|
||||
(§15), then delete the now-redundant `.map(ToString::to_string).collect()`
|
||||
at all 7 call sites. Self-contained to `signed_git`'s public API plus a
|
||||
|
||||
Reference in New Issue
Block a user