This commit is contained in:
2026-04-27 14:23:19 +08:00
parent 09d3fe59b3
commit fa2dbb310b
75 changed files with 7363 additions and 1487 deletions

View File

@@ -4,6 +4,7 @@ use axum::{
http::StatusCode,
response::Response,
};
use module_runtime::{SAVE_SNAPSHOT_VERSION, format_utc_micros};
use serde::Deserialize;
use serde_json::{Value, json};
use shared_contracts::runtime::{
@@ -70,8 +71,8 @@ pub async fn put_runtime_snapshot(
let updated_at_micros = offset_datetime_to_unix_micros(now);
let saved_at_micros = offset_datetime_to_unix_micros(saved_at);
let record = state
.put_runtime_snapshot_record(
let record = if is_non_persistent_runtime_snapshot(&payload.game_state) {
build_transient_runtime_snapshot_record(
user_id,
saved_at_micros,
payload.bottom_tab,
@@ -79,10 +80,21 @@ pub async fn put_runtime_snapshot(
payload.current_story,
updated_at_micros,
)
.await
.map_err(|error| {
runtime_save_error_response(&request_context, map_runtime_save_client_error(error))
})?;
} else {
state
.put_runtime_snapshot_record(
user_id,
saved_at_micros,
payload.bottom_tab,
payload.game_state,
payload.current_story,
updated_at_micros,
)
.await
.map_err(|error| {
runtime_save_error_response(&request_context, map_runtime_save_client_error(error))
})?
};
Ok(json_success_body(
Some(&request_context),
@@ -184,6 +196,52 @@ fn build_saved_game_snapshot_response(
}
}
fn build_transient_runtime_snapshot_record(
user_id: String,
saved_at_micros: i64,
bottom_tab: String,
game_state: Value,
current_story: Option<Value>,
updated_at_micros: i64,
) -> module_runtime::RuntimeSnapshotRecord {
// 中文注释:预览/测试入口可得到本次响应,但不能覆盖用户正式当前快照。
module_runtime::RuntimeSnapshotRecord {
user_id,
version: SAVE_SNAPSHOT_VERSION,
saved_at: format_utc_micros(saved_at_micros),
saved_at_micros,
bottom_tab,
game_state_json: game_state.to_string(),
current_story_json: current_story.as_ref().map(Value::to_string),
game_state,
current_story,
created_at_micros: updated_at_micros,
updated_at_micros,
}
}
fn is_non_persistent_runtime_snapshot(game_state: &Value) -> bool {
let Some(game_state) = game_state.as_object() else {
return false;
};
if game_state
.get("runtimePersistenceDisabled")
.and_then(Value::as_bool)
.unwrap_or(false)
{
return true;
}
matches!(
game_state
.get("runtimeMode")
.and_then(Value::as_str)
.map(str::trim),
Some("preview") | Some("test")
)
}
fn build_profile_save_archive_summary_response(
record: &module_runtime::RuntimeProfileSaveArchiveRecord,
) -> ProfileSaveArchiveSummaryResponse {