Fix really stupid oversight in the backend that caused all data to get messed up
All checks were successful
/ Push Docker image to local registry (push) Successful in 3m9s

We were saving all data into a single rocksdb which caused everything to
conflict with each other. This caused edits in one note to delete
content in all other notes.
This commit is contained in:
kalle 2025-04-14 22:42:48 +02:00
parent 32e9e1f725
commit e3cee4e596
2 changed files with 24 additions and 15 deletions

View file

@ -56,10 +56,6 @@ Yes, another rewrite was needed. Again.
- STRETCH: Contacts support. Same notes as caldav support. - STRETCH: Contacts support. Same notes as caldav support.
## Known bugs
- Offline edits in the canvas (excalidraw) note type cause all state to be lost. This might be even more severe, not requiring offline edits.
## Ideas ## Ideas
- Maybe rename Todos to Tasks, since they also contain doing, done, deadline, and idea types. Plus it's just a nicer name. - Maybe rename Todos to Tasks, since they also contain doing, done, deadline, and idea types. Plus it's just a nicer name.

View file

@ -20,6 +20,7 @@ use openidconnect::{
use rand::{distr::Alphanumeric, rng, Rng}; use rand::{distr::Alphanumeric, rng, Rng};
use rocksdb::TransactionDB; use rocksdb::TransactionDB;
use sha2::Sha256; use sha2::Sha256;
use std::fs;
use std::{ use std::{
char, char,
collections::HashMap, collections::HashMap,
@ -96,37 +97,37 @@ impl Reject for AuthError {}
struct Connection { struct Connection {
bcast: BroadcastGroup, bcast: BroadcastGroup,
// This is purely here to keep the connection to the DB alive while there is at least one db: Arc<TransactionDB>,
// connection.
#[allow(dyn_drop)] #[allow(dyn_drop)]
_db_subscription: Arc<dyn Drop + Send + Sync>, _db_sub: Arc<dyn Drop + Send + Sync>,
} }
struct Server { struct Server {
// There is something to be said for keeping the broadcast group in memory for a bit after all // There is something to be said for keeping the broadcast group in memory for a bit after all
// clients disconnect, but for now we don't bother. // clients disconnect, but for now we don't bother.
pub open_docs: RwLock<HashMap<String, Weak<Connection>>>, pub open_docs: RwLock<HashMap<String, Weak<Connection>>>,
pub db: Arc<TransactionDB>,
pub http_client: reqwest::Client, pub http_client: reqwest::Client,
pub openid_client: OpenidClient, pub openid_client: OpenidClient,
pub signing_key: Hmac<Sha256>, pub signing_key: Hmac<Sha256>,
pub data_dir: PathBuf,
} }
impl Server { impl Server {
pub fn new( pub fn new(
db: TransactionDB,
http_client: reqwest::Client, http_client: reqwest::Client,
openid_client: OpenidClient, openid_client: OpenidClient,
signing_key: Hmac<Sha256>, signing_key: Hmac<Sha256>,
data_dir: PathBuf,
) -> Self { ) -> Self {
Self { Self {
open_docs: RwLock::default(), open_docs: RwLock::default(),
db: Arc::new(db),
http_client, http_client,
openid_client, openid_client,
signing_key, signing_key,
data_dir,
} }
} }
pub async fn get_or_create_doc(&self, name: String) -> Arc<Connection> { pub async fn get_or_create_doc(&self, name: String) -> Arc<Connection> {
@ -138,10 +139,17 @@ impl Server {
let mut open_docs = self.open_docs.write().await; let mut open_docs = self.open_docs.write().await;
let doc = Doc::new(); let doc = Doc::new();
let data_dir = self.data_dir.join(name.clone());
if let Err(e) = fs::create_dir_all(&data_dir) {
panic!("Was unable to create data directory for note {}, due to the following error. Something is very wrong!\n{}", name, e)
}
let db =
Arc::new(TransactionDB::open_default(data_dir).expect("Failed to open DB"));
// Subscribe the DB to updates // Subscribe the DB to updates
let sub = { let sub = {
let db = self.db.clone(); let db = db.clone();
let name = name.clone(); let name = name.clone();
doc.observe_update_v1(move |_, e| { doc.observe_update_v1(move |_, e| {
let txn = RocksDBStore::from(db.transaction()); let txn = RocksDBStore::from(db.transaction());
@ -157,7 +165,7 @@ impl Server {
{ {
// Load document from DB // Load document from DB
let mut txn = doc.transact_mut(); let mut txn = doc.transact_mut();
let db_txn = RocksDBStore::from(self.db.transaction()); let db_txn = RocksDBStore::from(db.transaction());
db_txn.load_doc(&name, &mut txn).unwrap(); db_txn.load_doc(&name, &mut txn).unwrap();
} }
@ -165,7 +173,8 @@ impl Server {
let group = BroadcastGroup::new(awareness, 32).await; let group = BroadcastGroup::new(awareness, 32).await;
let connection = Arc::new(Connection { let connection = Arc::new(Connection {
bcast: group, bcast: group,
_db_subscription: sub, db,
_db_sub: sub,
}); });
open_docs.insert(name, Arc::downgrade(&connection)); open_docs.insert(name, Arc::downgrade(&connection));
@ -225,8 +234,12 @@ async fn main() {
) )
.await; .await;
let db = TransactionDB::open_default(&data_dir).expect("Failed to open DB"); let server = Arc::new(Server::new(
let server = Arc::new(Server::new(db, http_client, openid_client, signing_key)); http_client,
openid_client,
signing_key,
data_dir,
));
let ws = { let ws = {
let server = server.clone(); let server = server.clone();