From c65ff3d7faf454e5b6abadec5a0f116f8a74e3fa Mon Sep 17 00:00:00 2001 From: AyushAgrawal-A2 Date: Sun, 29 Sep 2024 04:23:19 +0530 Subject: [PATCH 1/2] chore: enable receive multiplayer transactions --- .../web-workers/quadraticCore/worker/core.ts | 29 +++++++++------ .../execution/receive_multiplayer.rs | 16 +++----- .../wasm_bindings/controller/transactions.rs | 37 ++++++++++--------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/quadratic-client/src/app/web-workers/quadraticCore/worker/core.ts b/quadratic-client/src/app/web-workers/quadraticCore/worker/core.ts index fe8d6b2186..33a459b2e7 100644 --- a/quadratic-client/src/app/web-workers/quadraticCore/worker/core.ts +++ b/quadratic-client/src/app/web-workers/quadraticCore/worker/core.ts @@ -316,20 +316,25 @@ class Core { this.clientQueue.push(async () => { if (!this.gridController) throw new Error('Expected gridController to be defined'); - for (let data of receive_transactions.transactions) { - // convert the base64 encoded string of operations into buffers - if (typeof data.operations === 'string') { - data.operations = Buffer.from(data.operations, 'base64'); - } + let formattedTransactions = receive_transactions.transactions.map((transaction) => ({ + id: transaction.id, + file_id: transaction.file_id, + sequence_num: transaction.sequence_num, + operations: + typeof transaction.operations === 'string' + ? Array.from(Buffer.from(transaction.operations, 'base64')) + : Array.from(transaction.operations), + })); + receive_transactions.transactions = []; - this.gridController.multiplayerTransaction(data.id, data.sequence_num, new Uint8Array(data.operations)); - } + const transactionsBuffer = JSON.stringify(formattedTransactions); + formattedTransactions = []; + + this.gridController.receiveMultiplayerTransactions(transactionsBuffer); + + // sends multiplayer synced to the client, to proceed from file loading screen + coreClient.sendMultiplayerSynced(); - // TODO(ddimaria): re-enable 5 - 7 days after we roll out the compressed - // transactions PR, so that we'll know all transactions are of the same version. - // - // const transactionsBuffer = JSON.stringify(receive_transactions.transactions); - // this.gridController.receiveMultiplayerTransactions(transactionsBuffer); if (await offline.unsentTransactionsCount()) { coreClient.sendMultiplayerState('syncing'); } else { diff --git a/quadratic-core/src/controller/execution/receive_multiplayer.rs b/quadratic-core/src/controller/execution/receive_multiplayer.rs index 9bac10bfd4..6534dd3889 100644 --- a/quadratic-core/src/controller/execution/receive_multiplayer.rs +++ b/quadratic-core/src/controller/execution/receive_multiplayer.rs @@ -116,11 +116,7 @@ impl GridController { ); } } - } - - if (cfg!(target_family = "wasm") || cfg!(test)) - && sequence_num >= self.transactions.last_sequence_num - { + } else if cfg!(target_family = "wasm") || cfg!(test) { crate::wasm_bindings::js::jsMultiplayerSynced(); } } @@ -226,7 +222,7 @@ impl GridController { } /// Received transactions from the server - pub fn received_transactions(&mut self, transactions: &[TransactionServer]) { + pub fn received_transactions(&mut self, transactions: Vec) { // used to track client changes when combining transactions let results = PendingTransaction { transaction_type: TransactionType::Multiplayer, @@ -235,7 +231,7 @@ impl GridController { self.rollback_unsaved_transactions(); // combine all transaction into one transaction - transactions.iter().for_each(|t| { + transactions.into_iter().for_each(|t| { let operations = Transaction::decompress_and_deserialize::>(&t.operations); @@ -689,7 +685,7 @@ mod tests { // todo... // assert_eq!(client_summary.request_transactions, Some(1)); - client.received_transactions(&[ + client.received_transactions(vec![ TransactionServer { file_id: Uuid::new_v4(), id: Uuid::new_v4(), @@ -768,7 +764,7 @@ mod tests { let transaction_id = client.async_transactions()[0].id; // we receive the first transaction while waiting for the async call to complete - client.received_transactions(&[TransactionServer { + client.received_transactions(vec![TransactionServer { file_id: Uuid::new_v4(), id: Uuid::new_v4(), sequence_num: 1, @@ -865,7 +861,7 @@ mod tests { let transaction_id = client.async_transactions()[0].id; // we receive the first transaction while waiting for the async call to complete - client.received_transactions(&[TransactionServer { + client.received_transactions(vec![TransactionServer { file_id: Uuid::new_v4(), id: Uuid::new_v4(), sequence_num: 1, diff --git a/quadratic-core/src/wasm_bindings/controller/transactions.rs b/quadratic-core/src/wasm_bindings/controller/transactions.rs index ea1226fc98..9053a7c139 100644 --- a/quadratic-core/src/wasm_bindings/controller/transactions.rs +++ b/quadratic-core/src/wasm_bindings/controller/transactions.rs @@ -1,7 +1,8 @@ use super::*; use crate::controller::{ active_transactions::unsaved_transactions::UnsavedTransaction, - operations::operation::Operation, transaction::Transaction, + operations::operation::Operation, + transaction::{Transaction, TransactionServer}, }; use uuid::Uuid; @@ -44,23 +45,23 @@ impl GridController { )?) } - // TODO(ddimaria): re-enable 5 - 7 days after we roll out the compressed - // transactions PR, so that we'll know all transactions are of the same version. - // - // #[wasm_bindgen(js_name = "receiveMultiplayerTransactions")] - // pub fn js_receive_multiplayer_transactions( - // &mut self, - // transactions: &str, - // ) -> Result { - // match serde_json::from_str::>(transactions) { - // Ok(transactions) => Ok(serde_wasm_bindgen::to_value( - // &self.received_transactions(&transactions[..]), - // )?), - // Err(e) => Err(JsValue::from_str(&format!( - // "Invalid transactions received in receiveMultiplayerTransactions: {e}" - // ))), - // } - // } + #[wasm_bindgen(js_name = "receiveMultiplayerTransactions")] + pub fn js_receive_multiplayer_transactions( + &mut self, + transactions: String, + ) -> Result { + match serde_json::from_str::>(&transactions) { + Ok(transactions) => Ok(serde_wasm_bindgen::to_value( + &self.received_transactions(transactions), + )?), + Err(e) => { + dbgjs!(format!("{transactions}")); + Err(JsValue::from_str(&format!( + "Invalid transactions received in receiveMultiplayerTransactions: {e}" + ))) + } + } + } #[wasm_bindgen(js_name = "applyOfflineUnsavedTransaction")] pub fn js_apply_offline_unsaved_transaction( From 366335dc31b22314a662082e987e68d802ba5e39 Mon Sep 17 00:00:00 2001 From: AyushAgrawal-A2 Date: Tue, 1 Oct 2024 03:21:59 +0530 Subject: [PATCH 2/2] add todo --- .../src/app/web-workers/quadraticCore/worker/core.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/quadratic-client/src/app/web-workers/quadraticCore/worker/core.ts b/quadratic-client/src/app/web-workers/quadraticCore/worker/core.ts index 33a459b2e7..f50425a471 100644 --- a/quadratic-client/src/app/web-workers/quadraticCore/worker/core.ts +++ b/quadratic-client/src/app/web-workers/quadraticCore/worker/core.ts @@ -327,6 +327,7 @@ class Core { })); receive_transactions.transactions = []; + // TODO(ayush): find a better way to do this, avoid JSON.stringify and pass the buffer directly const transactionsBuffer = JSON.stringify(formattedTransactions); formattedTransactions = [];