community: every ledger takes its write lock, so the inbox check can no longer land on top of a friend accept

This commit is contained in:
KeelrLeek committed 2026-09-03 11:51:35 -05:00
1 parent 07227a90a7
commit 4d03cf849b
6 files changed
+89 -29

No files matched your search

+9 -1
View File
@@ -30,6 +30,7 @@ use crate::persona;
use crate::pipeline::LibraryState;
use crate::playlists;
use crate::shared_playlists::{self, Published};
use crate::ledger;
use crate::slsk_link;
use crate::spaces;
use crate::state::AppState;
@@ -192,8 +193,11 @@ fn board_id(owner: &[u8; 32], uuid: &[u8; 16]) -> String {
format!("{}/{}", b58(owner), b58(uuid))
}
/// Both the file the ledger lives in and the key its write lock is taken on.
const LEDGER_FILE: &str = "boards.json";
fn path(app: &tauri::AppHandle) -> Result<PathBuf, String> {
Ok(app.path().app_data_dir().map_err(|e| e.to_string())?.join("freenet").join("boards.json"))
Ok(app.path().app_data_dir().map_err(|e| e.to_string())?.join("freenet").join(LEDGER_FILE))
}
fn load(app: &tauri::AppHandle) -> Ledger {
path(app)
@@ -392,6 +396,7 @@ pub async fn open(app: &tauri::AppHandle, space_owner_b58: &str, space_b58: &str
let have: Vec<[u8; 32]> = board.authority.as_ref().map(|a| a.contributors.clone()).unwrap_or_default();
let same = want.iter().collect::<BTreeSet<_>>() == have.iter().collect::<BTreeSet<_>>();
if !same {
let _ledger = ledger::hold(LEDGER_FILE).await;
let bid = board_id(&pin.owner, &pin.uuid);
let mut l = load(app);
let rec = l.boards.get(&bid).cloned().unwrap_or_default();
@@ -517,6 +522,7 @@ pub async fn decide(app: &tauri::AppHandle, space_owner_b58: &str, space_b58: &s
return Err("the board has not reached this node".into());
}
let p = board.proposals.iter().find(|p| p.proposal_id == pid).cloned().ok_or("that proposal is no longer pending")?;
let ledger = ledger::hold(LEDGER_FILE).await;
let bid = board_id(&pin.owner, &pin.uuid);
let mut l = load(app);
let rec = l.boards.get(&bid).cloned().unwrap_or_default();
@@ -544,6 +550,8 @@ pub async fn decide(app: &tauri::AppHandle, space_owner_b58: &str, space_b58: &s
l.boards.insert(bid, BoardRecord { last_seq: seq, ..rec });
save(app, &l)?;
log::info!("proposals: decision {} ({}) on board {}", seq, if accept { "accept" } else { "reject" }, b58(&pin.uuid));
// open() takes this same ledger; the write is done, so let go first.
drop(ledger);
open(app, space_owner_b58, space_b58).await
}