Files
OpenFUT-Core/src/services/game_ext.rs
T

35 lines
1.3 KiB
Rust

//! Generic read/write for [`crate::models::game_ext`] opaque state.
//!
//! Core never interprets the payload. Writes happen INSIDE the owning entity's
//! transaction (see `squad::replace_squad_with_extension`) so the canonical
//! entity and its opaque extension commit atomically — there is deliberately no
//! standalone "write extension" entry point that could desync the two.
use crate::db::Pool;
use crate::error::AppResult;
use crate::models::game_ext::GameEntityExt;
/// Fetch the stored opaque extension for a scoped entity, or `None`. The caller
/// compares `canonical_fingerprint` against the entity's *current* fingerprint to
/// decide freshness — this layer does not know how to fingerprint any entity.
pub async fn get_ext(
pool: &Pool,
game_id: &str,
entity_kind: &str,
entity_id: &str,
namespace: &str,
) -> AppResult<Option<GameEntityExt>> {
let row = sqlx::query_as::<_, GameEntityExt>(
"SELECT game_id, entity_kind, entity_id, namespace, schema_version, \
canonical_fingerprint, payload, updated_at FROM game_entity_ext \
WHERE game_id = ? AND entity_kind = ? AND entity_id = ? AND namespace = ?",
)
.bind(game_id)
.bind(entity_kind)
.bind(entity_id)
.bind(namespace)
.fetch_optional(pool)
.await?;
Ok(row)
}