fix: handle operation results before the busy guard so they clear it
This commit is contained in:
parent
e9e40bca36
commit
96f3748086
1 changed files with 114 additions and 72 deletions
186
src/app.rs
186
src/app.rs
|
|
@ -389,6 +389,80 @@ impl Carrier {
|
|||
}
|
||||
Task::none()
|
||||
}
|
||||
// Results pass regardless of the busy flag: each one clears the
|
||||
// operation it belongs to, so swallowing it would deadlock.
|
||||
Message::PinOffered(result) => {
|
||||
self.done();
|
||||
match result {
|
||||
Ok(Some((addr, key))) => {
|
||||
self.pin_offer = Some((addr, key));
|
||||
self.note(
|
||||
"The server presented this key. Pin it only if the fingerprint \
|
||||
matches what the operator published."
|
||||
.into(),
|
||||
);
|
||||
Task::none()
|
||||
}
|
||||
Ok(None) => {
|
||||
self.note("This server's key is already pinned.".into());
|
||||
Task::none()
|
||||
}
|
||||
Err(e) => {
|
||||
self.fail(e);
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::Pinned(result) => {
|
||||
self.done();
|
||||
match result {
|
||||
Ok(()) => self.note("server key pinned".into()),
|
||||
Err(e) => self.fail(e),
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::Exported(result) => {
|
||||
self.done();
|
||||
match result {
|
||||
Ok((note, text)) => {
|
||||
self.backup_text = Some(text);
|
||||
self.note(note);
|
||||
Task::none()
|
||||
}
|
||||
Err(e) => {
|
||||
self.fail(e);
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::SnapshotLoaded(result) => {
|
||||
self.done();
|
||||
match result {
|
||||
Ok(snap) => {
|
||||
self.share_qr = qr_code::Data::new(
|
||||
format!("smol://{}/{}", snap.who.address, snap.who.key).as_bytes(),
|
||||
)
|
||||
.ok();
|
||||
self.lists = snap.lists.clone();
|
||||
self.snapshot = Some(snap);
|
||||
Task::none()
|
||||
}
|
||||
Err(e) => {
|
||||
self.fail(e);
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::Generic(result) => {
|
||||
self.done();
|
||||
match result {
|
||||
Ok(note) => self.refresh_after(note),
|
||||
Err(e) => {
|
||||
self.fail(e);
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
_ if self.busy.is_some() => Task::none(),
|
||||
Message::OnboardCreate => {
|
||||
let master = ops::new_master();
|
||||
|
|
@ -477,28 +551,6 @@ impl Carrier {
|
|||
self.pin_offer = None;
|
||||
Task::none()
|
||||
}
|
||||
Message::PinOffered(result) => {
|
||||
self.done();
|
||||
match result {
|
||||
Ok(Some((addr, key))) => {
|
||||
self.pin_offer = Some((addr, key));
|
||||
self.note(
|
||||
"The server presented this key. Pin it only if the fingerprint \
|
||||
matches what the operator published."
|
||||
.into(),
|
||||
);
|
||||
Task::none()
|
||||
}
|
||||
Ok(None) => {
|
||||
self.note("This server's key is already pinned.".into());
|
||||
Task::none()
|
||||
}
|
||||
Err(e) => {
|
||||
self.fail(e);
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::PinAccept => {
|
||||
let Some((addr, key)) = self.pin_offer.take() else {
|
||||
return Task::none();
|
||||
|
|
@ -507,14 +559,6 @@ impl Carrier {
|
|||
ops::pin(&store, &addr, &key)
|
||||
})
|
||||
}
|
||||
Message::Pinned(result) => {
|
||||
self.done();
|
||||
match result {
|
||||
Ok(()) => self.note("server key pinned".into()),
|
||||
Err(e) => self.fail(e),
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
Message::SignupRegister => {
|
||||
let Some(addr) = self.signup_address() else {
|
||||
self.fail("enter user and host".into());
|
||||
|
|
@ -878,20 +922,6 @@ impl Carrier {
|
|||
.map(|(path, text)| (format!("backup written to {}", path.display()), text))
|
||||
})
|
||||
}
|
||||
Message::Exported(result) => {
|
||||
self.done();
|
||||
match result {
|
||||
Ok((note, text)) => {
|
||||
self.backup_text = Some(text);
|
||||
self.note(note);
|
||||
Task::none()
|
||||
}
|
||||
Err(e) => {
|
||||
self.fail(e);
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::ImportPressed => {
|
||||
let text = self.import_body.text();
|
||||
if text.trim().is_empty() {
|
||||
|
|
@ -901,34 +931,46 @@ impl Carrier {
|
|||
ops::import_backup(&store, &master, &text)
|
||||
})
|
||||
}
|
||||
Message::SnapshotLoaded(result) => {
|
||||
self.done();
|
||||
match result {
|
||||
Ok(snap) => {
|
||||
self.share_qr = qr_code::Data::new(
|
||||
format!("smol://{}/{}", snap.who.address, snap.who.key).as_bytes(),
|
||||
)
|
||||
.ok();
|
||||
self.lists = snap.lists.clone();
|
||||
self.snapshot = Some(snap);
|
||||
Task::none()
|
||||
}
|
||||
Err(e) => {
|
||||
self.fail(e);
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::Generic(result) => {
|
||||
self.done();
|
||||
match result {
|
||||
Ok(note) => self.refresh_after(note),
|
||||
Err(e) => {
|
||||
self.fail(e);
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn app() -> Carrier {
|
||||
let dir = tempfile::tempdir().unwrap().keep();
|
||||
let (app, _task) = Carrier::boot(dir);
|
||||
app
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn results_clear_the_busy_flag_instead_of_deadlocking() {
|
||||
let mut app = app();
|
||||
app.busy = Some("registering".into());
|
||||
let _ = app.update(Message::Generic(Err("boom".into())));
|
||||
assert!(app.busy.is_none());
|
||||
assert!(app.status_error);
|
||||
|
||||
app.busy = Some("registering".into());
|
||||
let _ = app.update(Message::SnapshotLoaded(Err("boom".into())));
|
||||
assert!(app.busy.is_none());
|
||||
|
||||
app.busy = Some("registering".into());
|
||||
let _ = app.update(Message::Generic(Ok("registered".into())));
|
||||
// The result was handled: the note landed and the refresh it
|
||||
// triggers is the new busy operation.
|
||||
assert_eq!(app.status.as_deref(), Some("registered"));
|
||||
assert_eq!(app.busy.as_deref(), Some("refreshing"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn actions_are_swallowed_while_busy() {
|
||||
let mut app = app();
|
||||
app.master = Some([0u8; KEY_LEN]);
|
||||
app.busy = Some("fetching".into());
|
||||
let _ = app.update(Message::FetchPressed);
|
||||
assert_eq!(app.busy.as_deref(), Some("fetching"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue