diff --git a/frontend/history-ui/src/lib/types/WebSocketVaultPathChange.ts b/frontend/history-ui/src/lib/types/WebSocketVaultPathChange.ts index a0af0a7b..6ae24f75 100644 --- a/frontend/history-ui/src/lib/types/WebSocketVaultPathChange.ts +++ b/frontend/history-ui/src/lib/types/WebSocketVaultPathChange.ts @@ -1,3 +1,3 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type WebSocketVaultPathChange = { vaultUpdateId: number, documentId: string, relativePath: string, updatedDate: string, userId: string, deviceId: string, }; +export type WebSocketVaultPathChange = { vaultUpdateId: number, documentId: string, relativePath: string, }; diff --git a/frontend/sync-client/src/services/types/WebSocketVaultPathChange.ts b/frontend/sync-client/src/services/types/WebSocketVaultPathChange.ts index f4b5bb84..f59ca5a5 100644 --- a/frontend/sync-client/src/services/types/WebSocketVaultPathChange.ts +++ b/frontend/sync-client/src/services/types/WebSocketVaultPathChange.ts @@ -1,3 +1,3 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export interface WebSocketVaultPathChange { vaultUpdateId: number, documentId: string, relativePath: string, updatedDate: string, userId: string, deviceId: string, } +export interface WebSocketVaultPathChange { vaultUpdateId: number, documentId: string, relativePath: string, } diff --git a/sync-server/src/app_state/database.rs b/sync-server/src/app_state/database.rs index 83d2561c..c9ea9746 100644 --- a/sync-server/src/app_state/database.rs +++ b/sync-server/src/app_state/database.rs @@ -14,7 +14,7 @@ use sqlx::{ConnectOptions, Connection, sqlite::SqliteConnectOptions, types::chro pub mod models; -/// Sentinel error indicating the SQLite database is busy (SQLITE_BUSY). +/// Sentinel error indicating the `SQLite` database is busy (`SQLITE_BUSY`). /// Handlers can downcast to this to return 429 instead of 500. #[derive(Debug, thiserror::Error)] #[error("Database is busy")] @@ -76,11 +76,11 @@ pub struct Database { config: DatabaseConfig, broadcasts: Broadcasts, connection_pools: Arc>>>, - /// Per-vault write serialization. SQLite allows only one writer at a + /// Per-vault write serialization. `SQLite` allows only one writer at a /// time; `BEGIN IMMEDIATE` on a second connection blocks until the first /// commits (up to `busy_timeout`). Under concurrent load the blocked /// connections consume the pool, starving even read-only requests. - /// This mutex moves the wait from the SQLite layer (where it holds a + /// This mutex moves the wait from the `SQLite` layer (where it holds a /// pool connection) to the Tokio layer (where it holds nothing). write_locks: Arc>>>>, /// Monotonic epoch for lock-free `last_accessed_ms` timestamps @@ -768,9 +768,6 @@ impl Database { vault_update_id: version.vault_update_id, document_id: version.document_id, relative_path: version.relative_path.clone(), - updated_date: version.updated_date, - user_id: version.user_id.clone(), - device_id: version.device_id.clone(), }, )), ); diff --git a/sync-server/src/app_state/websocket/broadcasts.rs b/sync-server/src/app_state/websocket/broadcasts.rs index 0b49fa27..fcd4e9dd 100644 --- a/sync-server/src/app_state/websocket/broadcasts.rs +++ b/sync-server/src/app_state/websocket/broadcasts.rs @@ -82,11 +82,7 @@ impl Broadcasts { /// Synchronous: safe to invoke from a handler between `commit()` and /// function return without worrying about task cancellation dropping /// the broadcast mid-flight. Failures are logged, never propagated. - pub fn send_document_update( - &self, - vault: VaultId, - document: WebSocketServerMessageWithOrigin, - ) { + pub fn send_document_update(&self, vault: VaultId, document: WebSocketServerMessageWithOrigin) { let mut tx_map = self .tx .lock() diff --git a/sync-server/src/app_state/websocket/models.rs b/sync-server/src/app_state/websocket/models.rs index 282aa03a..9ed52400 100644 --- a/sync-server/src/app_state/websocket/models.rs +++ b/sync-server/src/app_state/websocket/models.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use ts_rs::TS; use crate::app_state::database::models::{ - DeviceId, DocumentId, DocumentVersionWithoutContent, UserId, VaultUpdateId, + DeviceId, DocumentId, DocumentVersionWithoutContent, VaultUpdateId, }; #[derive(TS, Deserialize, Clone, Debug)] diff --git a/sync-server/src/app_state/websocket/utils.rs b/sync-server/src/app_state/websocket/utils.rs index 24bc287a..4c959a76 100644 --- a/sync-server/src/app_state/websocket/utils.rs +++ b/sync-server/src/app_state/websocket/utils.rs @@ -33,9 +33,9 @@ pub fn get_authenticated_handshake( let user = auth(state, handshake.token.trim(), vault_id)?; Ok(AuthenticatedWebSocketHandshake { handshake, user }) } - WebSocketClientMessage::CursorPositions(_) => Err( - unauthenticated_error(anyhow::anyhow!("Expected a handshake message")), - ), + WebSocketClientMessage::CursorPositions(_) => Err(unauthenticated_error( + anyhow::anyhow!("Expected a handshake message"), + )), } } else { Err(unauthenticated_error(anyhow::anyhow!( diff --git a/sync-server/src/config/database_config.rs b/sync-server/src/config/database_config.rs index 21e79d29..a6f57e1f 100644 --- a/sync-server/src/config/database_config.rs +++ b/sync-server/src/config/database_config.rs @@ -38,7 +38,7 @@ fn default_cursor_timeout() -> Duration { impl DatabaseConfig { pub fn validate(&self) -> Result<()> { ensure!( - self.databases_directory_path.as_os_str().len() > 0, + !self.databases_directory_path.as_os_str().is_empty(), "databases_directory_path must not be empty" ); ensure!( diff --git a/sync-server/src/config/logging_config.rs b/sync-server/src/config/logging_config.rs index 016dbc46..dae67288 100644 --- a/sync-server/src/config/logging_config.rs +++ b/sync-server/src/config/logging_config.rs @@ -5,7 +5,9 @@ use log::debug; use serde::{Deserialize, Serialize}; use crate::{ - consts::{DEFAULT_LOG_DIRECTORY, DEFAULT_LOG_LEVEL, DEFAULT_LOG_ROTATION_INTERVAL, DURATION_ZERO}, + consts::{ + DEFAULT_LOG_DIRECTORY, DEFAULT_LOG_LEVEL, DEFAULT_LOG_ROTATION_INTERVAL, DURATION_ZERO, + }, utils::log_level::LogLevel, }; @@ -27,7 +29,10 @@ impl LoggingConfig { !self.log_directory.is_empty(), "log_directory must not be an empty string" ); - ensure!(self.log_rotation > DURATION_ZERO, "log_rotation must be greater than 0"); + ensure!( + self.log_rotation > DURATION_ZERO, + "log_rotation must be greater than 0" + ); Ok(()) } } diff --git a/sync-server/src/errors.rs b/sync-server/src/errors.rs index 0dad0463..892db36f 100644 --- a/sync-server/src/errors.rs +++ b/sync-server/src/errors.rs @@ -98,9 +98,7 @@ impl IntoResponse for SyncServerError { Self::NotFound(_) => (StatusCode::NOT_FOUND, body).into_response(), Self::Unauthenticated(_) => (StatusCode::UNAUTHORIZED, body).into_response(), Self::PermissionDeniedError(_) => (StatusCode::FORBIDDEN, body).into_response(), - Self::TooManyRequests(_) => { - (StatusCode::TOO_MANY_REQUESTS, body).into_response() - } + Self::TooManyRequests(_) => (StatusCode::TOO_MANY_REQUESTS, body).into_response(), } } } @@ -171,7 +169,10 @@ pub fn too_many_requests_error(error: anyhow::Error) -> SyncServerError { /// Maps a `create_write_transaction` error to 429 if the database is busy, /// or 500 for all other failures. pub fn write_transaction_error(error: anyhow::Error) -> SyncServerError { - if error.downcast_ref::().is_some() { + if error + .downcast_ref::() + .is_some() + { too_many_requests_error(error) } else { server_error(error) diff --git a/sync-server/src/server/requests.rs b/sync-server/src/server/requests.rs index f0499194..e0468edc 100644 --- a/sync-server/src/server/requests.rs +++ b/sync-server/src/server/requests.rs @@ -40,4 +40,3 @@ pub struct UpdateTextDocumentVersion { #[ts(type = "Array")] pub content: Vec, } - diff --git a/sync-server/src/server/restore_document_version.rs b/sync-server/src/server/restore_document_version.rs index 7522e73c..5a806edd 100644 --- a/sync-server/src/server/restore_document_version.rs +++ b/sync-server/src/server/restore_document_version.rs @@ -20,7 +20,9 @@ use crate::{ }, }, config::user_config::User, - errors::{SyncServerError, client_error, not_found_error, server_error, write_transaction_error}, + errors::{ + SyncServerError, client_error, not_found_error, server_error, write_transaction_error, + }, utils::{find_first_available_path::find_first_available_path, normalize::normalize}, }; diff --git a/sync-server/src/server/websocket.rs b/sync-server/src/server/websocket.rs index 41bf4754..4540539a 100644 --- a/sync-server/src/server/websocket.rs +++ b/sync-server/src/server/websocket.rs @@ -1,15 +1,3 @@ -use anyhow::Context; -use axum::{ - extract::{ - Path, State, - ws::{Message, WebSocket, WebSocketUpgrade}, - }, - response::Response, -}; -use futures::sink::SinkExt; -use futures::stream::StreamExt; -use log::{debug, info, warn}; -use serde::Deserialize; use crate::{ app_state::{ AppState, @@ -25,12 +13,23 @@ use crate::{ }, }, consts::{ - HANDSHAKE_TIMEOUT, MAX_CURSORS_PER_DOCUMENT, MAX_CURSOR_DOCUMENTS, - MAX_RELATIVE_PATH_LEN, + HANDSHAKE_TIMEOUT, MAX_CURSOR_DOCUMENTS, MAX_CURSORS_PER_DOCUMENT, MAX_RELATIVE_PATH_LEN, }, errors::{SyncServerError, client_error, server_error}, utils::normalize::normalize, }; +use anyhow::Context; +use axum::{ + extract::{ + Path, State, + ws::{Message, WebSocket, WebSocketUpgrade}, + }, + response::Response, +}; +use futures::sink::SinkExt; +use futures::stream::StreamExt; +use log::{debug, info, warn}; +use serde::Deserialize; /// Tracks a pending (not yet authenticated) WebSocket connection. /// Decrements the counter when dropped, ensuring cleanup even if @@ -39,8 +38,7 @@ struct PendingWsGuard(std::sync::Arc); impl Drop for PendingWsGuard { fn drop(&mut self) { - self.0 - .fetch_sub(1, std::sync::atomic::Ordering::Relaxed); + self.0.fetch_sub(1, std::sync::atomic::Ordering::Relaxed); } } @@ -112,9 +110,7 @@ async fn websocket( drop(pending_guard); let max_clients = state.config.server.max_clients_per_vault; - let mut broadcast_receiver = match state - .broadcasts - .get_receiver(vault_id.clone(), max_clients) + let mut broadcast_receiver = match state.broadcasts.get_receiver(vault_id.clone(), max_clients) { Ok(receiver) => receiver, Err(err) => { @@ -229,7 +225,9 @@ async fn websocket( && doc.relative_path.len() <= MAX_RELATIVE_PATH_LEN }); if !valid { - warn!("Cursor update rejected: a document exceeds cursor or path length limits"); + warn!( + "Cursor update rejected: a document exceeds cursor or path length limits" + ); continue; } diff --git a/sync-server/src/utils/find_first_available_path.rs b/sync-server/src/utils/find_first_available_path.rs index caaa1624..eddd81d2 100644 --- a/sync-server/src/utils/find_first_available_path.rs +++ b/sync-server/src/utils/find_first_available_path.rs @@ -4,7 +4,6 @@ use anyhow::Result; use log::{debug, info}; use sqlx::sqlite::SqliteConnection; - pub async fn find_first_available_path( vault_id: &VaultId, sanitized_relative_path: &str, diff --git a/sync-server/src/utils/sanitize_path.rs b/sync-server/src/utils/sanitize_path.rs index 46dcc64c..05100f68 100644 --- a/sync-server/src/utils/sanitize_path.rs +++ b/sync-server/src/utils/sanitize_path.rs @@ -34,7 +34,10 @@ pub fn sanitize_path(path: &str) -> Result { .collect::>() .join("/"); - ensure!(!result.is_empty(), "Relative path is empty after sanitization"); + ensure!( + !result.is_empty(), + "Relative path is empty after sanitization" + ); Ok(result) }