diff --git a/arma/server/extension/Cargo.toml b/arma/server/extension/Cargo.toml index dd91c69..41bb122 100644 --- a/arma/server/extension/Cargo.toml +++ b/arma/server/extension/Cargo.toml @@ -18,7 +18,7 @@ forge-services = { path = "../../../lib/services" } forge-shared = { path = "../../../lib/shared" } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -surrealdb = { version = "2", default-features = false, features = ["protocol-http", "rustls"] } +surrealdb = { version = "3", default-features = false, features = ["protocol-http", "rustls"] } tokio = { workspace = true } toml = "1.1.2" uuid = { workspace = true } diff --git a/arma/server/extension/README.md b/arma/server/extension/README.md index 128af85..ea72deb 100644 --- a/arma/server/extension/README.md +++ b/arma/server/extension/README.md @@ -4,6 +4,8 @@ The Forge server extension is the Rust backend for server-side game systems. It exposes domain commands through `arma-rs`, runs a shared Tokio runtime, and persists durable state through SurrealDB. +This extension build targets SurrealDB `3.x`. + ## Responsibilities - Register extension command groups for actor, bank, garage, locker, org, diff --git a/arma/server/extension/src/storage/common.rs b/arma/server/extension/src/storage/common.rs index 800ef50..00aa0c8 100644 --- a/arma/server/extension/src/storage/common.rs +++ b/arma/server/extension/src/storage/common.rs @@ -1,4 +1,5 @@ use super::*; +use serde_json::Value as JsonValue; pub(super) fn surreal_select( table: &'static str, @@ -10,11 +11,17 @@ where { let id = id.to_string(); RUNTIME.block_on(async move { - surreal::client() + let value: Option = surreal::client() .await? .select((table, id.as_str())) .await - .map_err(|error| format!("SurrealDB {} select failed: {}", label, error)) + .map_err(|error| format!("SurrealDB {} select failed: {}", label, error))?; + value + .map(|record| { + serde_json::from_value(record) + .map_err(|error| format!("SurrealDB {} decode failed: {}", label, error)) + }) + .transpose() }) } @@ -23,11 +30,18 @@ where T: DeserializeOwned, { RUNTIME.block_on(async move { - surreal::client() + let values: Vec = surreal::client() .await? .select(table) .await - .map_err(|error| format!("SurrealDB {} select all failed: {}", label, error)) + .map_err(|error| format!("SurrealDB {} select all failed: {}", label, error))?; + values + .into_iter() + .map(|record| { + serde_json::from_value(record) + .map_err(|error| format!("SurrealDB {} decode failed: {}", label, error)) + }) + .collect() }) } @@ -44,7 +58,7 @@ where let record = serde_json::to_value(record) .map_err(|error| format!("SurrealDB {} serialize failed: {}", label, error))?; RUNTIME.block_on(async move { - let _: Option = surreal::client() + let _: Option = surreal::client() .await? .upsert((table, id.as_str())) .content(record) @@ -60,7 +74,7 @@ where { let id = id.to_string(); RUNTIME.block_on(async move { - let _: Option = surreal::client() + let _: Option = surreal::client() .await? .delete((table, id.as_str())) .await @@ -97,9 +111,16 @@ where .bind(("value", value)) .await .map_err(|error| format!("SurrealDB {} select by field failed: {}", label, error))?; - response + let values: Vec = response .take(0) - .map_err(|error| format!("SurrealDB {} select by field failed: {}", label, error)) + .map_err(|error| format!("SurrealDB {} select by field failed: {}", label, error))?; + values + .into_iter() + .map(|record| { + serde_json::from_value(record) + .map_err(|error| format!("SurrealDB {} decode failed: {}", label, error)) + }) + .collect() }) } diff --git a/arma/server/extension/src/storage/garage.rs b/arma/server/extension/src/storage/garage.rs index 6504c04..2680df1 100644 --- a/arma/server/extension/src/storage/garage.rs +++ b/arma/server/extension/src/storage/garage.rs @@ -200,6 +200,7 @@ struct GarageUnlockRecord { uid: String, category: String, classname: String, + #[serde(skip_serializing_if = "Option::is_none")] source: Option, } diff --git a/arma/server/extension/src/storage/locker.rs b/arma/server/extension/src/storage/locker.rs index c7194be..a00d6b3 100644 --- a/arma/server/extension/src/storage/locker.rs +++ b/arma/server/extension/src/storage/locker.rs @@ -189,6 +189,7 @@ struct LockerUnlockRecord { uid: String, category: String, classname: String, + #[serde(skip_serializing_if = "Option::is_none")] source: Option, } diff --git a/arma/server/extension/src/storage/org.rs b/arma/server/extension/src/storage/org.rs index af69acd..905c462 100644 --- a/arma/server/extension/src/storage/org.rs +++ b/arma/server/extension/src/storage/org.rs @@ -96,7 +96,7 @@ impl OrgRepository for OrgStorageRepository { } } -#[derive(Debug, Default, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize)] struct SurrealOrgRecord { #[serde(default)] org_id: String, diff --git a/arma/server/extension/src/surreal.rs b/arma/server/extension/src/surreal.rs index 560d969..74df542 100644 --- a/arma/server/extension/src/surreal.rs +++ b/arma/server/extension/src/surreal.rs @@ -109,8 +109,8 @@ async fn connect(config: SurrealConfig) -> Result { if let (Some(username), Some(password)) = (&config.username, &config.password) { db.signin(Root { - username: username.as_str(), - password: password.as_str(), + username: username.clone(), + password: password.clone(), }) .await .map_err(|error| error.to_string())?; diff --git a/docus/content/1.getting-started/4.surrealdb-setup.md b/docus/content/1.getting-started/4.surrealdb-setup.md index 918a801..252a376 100644 --- a/docus/content/1.getting-started/4.surrealdb-setup.md +++ b/docus/content/1.getting-started/4.surrealdb-setup.md @@ -4,6 +4,9 @@ Forge uses SurrealDB for durable storage. The Rust server extension connects to SurrealDB on startup and applies Forge schema modules automatically, so setup comes down to running a reachable database and matching the Forge config. +Forge currently targets the SurrealDB `3.x` server line. Do not pair this +build of the extension with a `2.x` SurrealDB server. + ## Choose the Right Path ### Developer or Server Operator