forked from Keelrleek/SoulStream
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:
1 parent
07227a90a7
commit
4d03cf849b
6 files changed
+89
-29
No files matched your search
+21
-6
@@ -25,6 +25,7 @@ use serde::{Deserialize, Serialize};
|
||||
use tauri::{Emitter, Manager};
|
||||
|
||||
use crate::inbox::{self, Cargo, SpaceInvite, SpaceKeyCargo};
|
||||
use crate::ledger;
|
||||
use crate::persona;
|
||||
use crate::slsk_link;
|
||||
use crate::state::AppState;
|
||||
@@ -159,8 +160,11 @@ fn path(app: &tauri::AppHandle) -> Result<PathBuf, String> {
|
||||
.app_data_dir()
|
||||
.map_err(|e| e.to_string())?
|
||||
.join("freenet")
|
||||
.join("spaces.json"))
|
||||
.join(LEDGER_FILE))
|
||||
}
|
||||
/// Both the file the ledger lives in and the key its write lock is taken on.
|
||||
const LEDGER_FILE: &str = "spaces.json";
|
||||
|
||||
fn load(app: &tauri::AppHandle) -> Ledger {
|
||||
path(app)
|
||||
.ok()
|
||||
@@ -363,6 +367,7 @@ pub async fn create(app: &tauri::AppHandle, name: &str, description: &str, priva
|
||||
keys,
|
||||
last_epoch: 1,
|
||||
};
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut l = load(app);
|
||||
l.spaces.insert(record_id(&rec.owner, &rec.space_id), rec.clone());
|
||||
save(app, &l)?;
|
||||
@@ -374,6 +379,7 @@ pub async fn open(app: &tauri::AppHandle, owner_b58: &str, space_b58: &str) -> R
|
||||
let me = my_key(app).await?;
|
||||
let owner = key_of(owner_b58)?;
|
||||
let space_id = id_of(space_b58)?;
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut l = load(app);
|
||||
let rid = record_id(owner_b58, space_b58);
|
||||
let rec = l.spaces.get(&rid).cloned().ok_or("not a Space this device knows")?;
|
||||
@@ -475,6 +481,7 @@ pub async fn invite(app: &tauri::AppHandle, owner_b58: &str, space_b58: &str, pe
|
||||
})
|
||||
.await?;
|
||||
let rid = record_id(owner_b58, space_b58);
|
||||
let ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut l = load(app);
|
||||
let rec = l.spaces.get_mut(&rid).ok_or("not a Space this device knows")?;
|
||||
let mut key = None;
|
||||
@@ -493,6 +500,8 @@ pub async fn invite(app: &tauri::AppHandle, owner_b58: &str, space_b58: &str, pe
|
||||
)
|
||||
.await?;
|
||||
log::info!("spaces: invited {persona_key} to {:?} (epoch {})", c.name, c.epoch);
|
||||
// open() takes this same ledger; the write is done, so let go first.
|
||||
drop(ledger);
|
||||
open(app, owner_b58, space_b58).await
|
||||
}
|
||||
|
||||
@@ -506,6 +515,7 @@ pub async fn remove_member(app: &tauri::AppHandle, owner_b58: &str, space_b58: &
|
||||
}
|
||||
let c = bump(app, me, owner, space_id, |c| c.members.retain(|m| m.key != gone)).await?;
|
||||
let rid = record_id(owner_b58, space_b58);
|
||||
let ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut l = load(app);
|
||||
let rec = l.spaces.get_mut(&rid).ok_or("not a Space this device knows")?;
|
||||
rec.last_epoch = c.epoch;
|
||||
@@ -523,6 +533,8 @@ pub async fn remove_member(app: &tauri::AppHandle, owner_b58: &str, space_b58: &
|
||||
} else {
|
||||
save(app, &l)?;
|
||||
}
|
||||
// open() takes this same ledger; the write is done, so let go first.
|
||||
drop(ledger);
|
||||
open(app, owner_b58, space_b58).await
|
||||
}
|
||||
|
||||
@@ -538,7 +550,8 @@ pub async fn set_pinned(app: &tauri::AppHandle, owner_b58: &str, space_b58: &str
|
||||
open(app, owner_b58, space_b58).await
|
||||
}
|
||||
|
||||
pub fn leave(app: &tauri::AppHandle, owner_b58: &str, space_b58: &str) -> Result<(), String> {
|
||||
pub async fn leave(app: &tauri::AppHandle, owner_b58: &str, space_b58: &str) -> Result<(), String> {
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut l = load(app);
|
||||
let rid = record_id(owner_b58, space_b58);
|
||||
if l.spaces.get(&rid).is_some_and(|r| r.my_role == "owner") {
|
||||
@@ -550,12 +563,13 @@ pub fn leave(app: &tauri::AppHandle, owner_b58: &str, space_b58: &str) -> Result
|
||||
|
||||
// ---------------------------------------------------------------- inbox cargo
|
||||
|
||||
pub(crate) fn on_inbox_invite(app: &tauri::AppHandle, sender: [u8; 32], inv: SpaceInvite) {
|
||||
pub(crate) async fn on_inbox_invite(app: &tauri::AppHandle, sender: [u8; 32], inv: SpaceInvite) {
|
||||
if sender != inv.owner {
|
||||
log::warn!("spaces: an invitation was sealed by someone other than the Space's owner");
|
||||
return;
|
||||
}
|
||||
let rid = record_id(&b58(&inv.owner), &b58(&inv.space_id));
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut l = load(app);
|
||||
let rec = l.spaces.entry(rid).or_insert_with(|| SpaceRecord {
|
||||
owner: b58(&inv.owner),
|
||||
@@ -579,11 +593,12 @@ pub(crate) fn on_inbox_invite(app: &tauri::AppHandle, sender: [u8; 32], inv: Spa
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn on_inbox_space_key(app: &tauri::AppHandle, sender: [u8; 32], sk: SpaceKeyCargo) {
|
||||
pub(crate) async fn on_inbox_space_key(app: &tauri::AppHandle, sender: [u8; 32], sk: SpaceKeyCargo) {
|
||||
if sender != sk.owner {
|
||||
return;
|
||||
}
|
||||
let rid = record_id(&b58(&sk.owner), &b58(&sk.space_id));
|
||||
let _ledger = ledger::hold(LEDGER_FILE).await;
|
||||
let mut l = load(app);
|
||||
let Some(rec) = l.spaces.get_mut(&rid) else { return };
|
||||
rec.keys.insert(sk.epoch.to_string(), b58(&sk.key));
|
||||
@@ -621,8 +636,8 @@ pub async fn space_set_pinned(app: tauri::AppHandle, owner: String, space: Strin
|
||||
set_pinned(&app, &owner, &space, playlist_owner, playlist_uuid).await
|
||||
}
|
||||
#[tauri::command]
|
||||
pub fn space_leave(app: tauri::AppHandle, owner: String, space: String) -> Result<(), String> {
|
||||
leave(&app, &owner, &space)
|
||||
pub async fn space_leave(app: tauri::AppHandle, owner: String, space: String) -> Result<(), String> {
|
||||
leave(&app, &owner, &space).await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in new issue
Block a user