推进 server-rs DDD 分层与新接口接线
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use crate::big_fish::tables::{big_fish_asset_slot, big_fish_creation_session};
|
||||
use crate::*;
|
||||
use module_big_fish::{EvaluateBigFishPublishReadinessCommand, evaluate_publish_readiness};
|
||||
|
||||
#[spacetimedb::procedure]
|
||||
pub fn generate_big_fish_asset(
|
||||
@@ -70,6 +71,16 @@ pub(crate) fn generate_big_fish_asset_tx(
|
||||
upsert_big_fish_asset_slot(ctx, slot);
|
||||
|
||||
let asset_slots = list_big_fish_asset_slots(ctx, &session.session_id);
|
||||
let readiness = evaluate_publish_readiness(
|
||||
EvaluateBigFishPublishReadinessCommand {
|
||||
session_id: session.session_id.clone(),
|
||||
owner_user_id: session.owner_user_id.clone(),
|
||||
draft: Some(draft.clone()),
|
||||
evaluated_at_micros: input.generated_at_micros,
|
||||
},
|
||||
&asset_slots,
|
||||
)
|
||||
.map_err(|error| error.to_string())?;
|
||||
let coverage = build_asset_coverage(Some(&draft), &asset_slots);
|
||||
let updated_at = Timestamp::from_micros_since_unix_epoch(input.generated_at_micros);
|
||||
let uses_placeholder = input
|
||||
@@ -90,7 +101,7 @@ pub(crate) fn generate_big_fish_asset_tx(
|
||||
}
|
||||
}
|
||||
.to_string();
|
||||
let next_stage = if coverage.publish_ready {
|
||||
let next_stage = if readiness.readiness.publish_ready {
|
||||
BigFishCreationStage::ReadyToPublish
|
||||
} else {
|
||||
BigFishCreationStage::AssetRefining
|
||||
@@ -100,19 +111,26 @@ pub(crate) fn generate_big_fish_asset_tx(
|
||||
owner_user_id: session.owner_user_id.clone(),
|
||||
seed_text: session.seed_text.clone(),
|
||||
current_turn: session.current_turn,
|
||||
progress_percent: if coverage.publish_ready { 96 } else { 88 },
|
||||
progress_percent: if readiness.readiness.publish_ready {
|
||||
96
|
||||
} else {
|
||||
88
|
||||
},
|
||||
stage: next_stage,
|
||||
anchor_pack_json: session.anchor_pack_json.clone(),
|
||||
draft_json: session.draft_json.clone(),
|
||||
asset_coverage_json: serialize_asset_coverage(&coverage)
|
||||
.map_err(|error| error.to_string())?,
|
||||
last_assistant_reply: Some(reply.clone()),
|
||||
publish_ready: coverage.publish_ready,
|
||||
publish_ready: readiness.readiness.publish_ready,
|
||||
play_count: session.play_count,
|
||||
created_at: session.created_at,
|
||||
updated_at,
|
||||
};
|
||||
replace_big_fish_session(ctx, &session, next_session);
|
||||
for event in readiness.events {
|
||||
emit_big_fish_publish_readiness_event(ctx, event)?;
|
||||
}
|
||||
|
||||
get_big_fish_session_tx(
|
||||
ctx,
|
||||
@@ -140,14 +158,22 @@ pub(crate) fn publish_big_fish_game_tx(
|
||||
.as_deref()
|
||||
.ok_or_else(|| "big_fish.draft 尚未编译".to_string())
|
||||
.and_then(|value| deserialize_draft(value).map_err(|error| error.to_string()))?;
|
||||
let coverage = build_asset_coverage(
|
||||
Some(&draft),
|
||||
&list_big_fish_asset_slots(ctx, &session.session_id),
|
||||
);
|
||||
if !coverage.publish_ready {
|
||||
let asset_slots = list_big_fish_asset_slots(ctx, &session.session_id);
|
||||
let readiness = evaluate_publish_readiness(
|
||||
EvaluateBigFishPublishReadinessCommand {
|
||||
session_id: session.session_id.clone(),
|
||||
owner_user_id: session.owner_user_id.clone(),
|
||||
draft: Some(draft.clone()),
|
||||
evaluated_at_micros: input.published_at_micros,
|
||||
},
|
||||
&asset_slots,
|
||||
)
|
||||
.map_err(|error| error.to_string())?;
|
||||
let coverage = build_asset_coverage(Some(&draft), &asset_slots);
|
||||
if !readiness.readiness.publish_ready {
|
||||
return Err(format!(
|
||||
"big_fish 发布校验未通过:{}",
|
||||
coverage.blockers.join(";")
|
||||
readiness.readiness.blockers.join(";")
|
||||
));
|
||||
}
|
||||
|
||||
@@ -170,6 +196,9 @@ pub(crate) fn publish_big_fish_game_tx(
|
||||
updated_at: published_at,
|
||||
};
|
||||
replace_big_fish_session(ctx, &session, next_session);
|
||||
for event in readiness.events {
|
||||
emit_big_fish_publish_readiness_event(ctx, event)?;
|
||||
}
|
||||
|
||||
get_big_fish_session_tx(
|
||||
ctx,
|
||||
|
||||
56
server-rs/crates/spacetime-module/src/big_fish/events.rs
Normal file
56
server-rs/crates/spacetime-module/src/big_fish/events.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use crate::*;
|
||||
|
||||
/// Big Fish 创作事件类型。
|
||||
///
|
||||
/// 事件表只承接跨层订阅和审计所需的轻量事实,正式作品状态仍以
|
||||
/// `big_fish_creation_session` 和 `big_fish_asset_slot` 为准。
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub enum BigFishEventKind {
|
||||
PublishReadinessEvaluated,
|
||||
}
|
||||
|
||||
#[spacetimedb::table(
|
||||
accessor = big_fish_event,
|
||||
public,
|
||||
event,
|
||||
index(accessor = by_big_fish_event_session_id, btree(columns = [session_id])),
|
||||
index(accessor = by_big_fish_event_owner_user_id, btree(columns = [owner_user_id]))
|
||||
)]
|
||||
pub struct BigFishEvent {
|
||||
#[primary_key]
|
||||
pub(crate) event_id: String,
|
||||
pub(crate) session_id: String,
|
||||
pub(crate) owner_user_id: String,
|
||||
pub(crate) event_kind: BigFishEventKind,
|
||||
pub(crate) publish_ready: bool,
|
||||
pub(crate) blockers_json: String,
|
||||
pub(crate) occurred_at: Timestamp,
|
||||
}
|
||||
|
||||
pub(crate) fn emit_big_fish_publish_readiness_event(
|
||||
ctx: &ReducerContext,
|
||||
event: BigFishDomainEvent,
|
||||
) -> Result<(), String> {
|
||||
let BigFishDomainEvent::PublishReadinessEvaluated {
|
||||
session_id,
|
||||
owner_user_id,
|
||||
publish_ready,
|
||||
blockers,
|
||||
occurred_at_micros,
|
||||
} = event;
|
||||
|
||||
let blockers_json = serde_json::to_string(&blockers)
|
||||
.map_err(|error| format!("big_fish.publish_readiness.blockers 序列化失败: {error}"))?;
|
||||
let state_slug = if publish_ready { "ready" } else { "blocked" };
|
||||
ctx.db.big_fish_event().insert(BigFishEvent {
|
||||
event_id: format!("bfevt_{session_id}_{occurred_at_micros}_{state_slug}"),
|
||||
session_id,
|
||||
owner_user_id,
|
||||
event_kind: BigFishEventKind::PublishReadinessEvaluated,
|
||||
publish_ready,
|
||||
blockers_json,
|
||||
occurred_at: Timestamp::from_micros_since_unix_epoch(occurred_at_micros),
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
mod assets;
|
||||
mod events;
|
||||
mod session;
|
||||
mod tables;
|
||||
|
||||
pub use assets::*;
|
||||
pub(crate) use events::*;
|
||||
pub use session::*;
|
||||
pub use tables::*;
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::runtime::{
|
||||
ProfilePlayedWorkUpsertInput, add_profile_observed_play_time, upsert_profile_played_work,
|
||||
};
|
||||
use crate::*;
|
||||
use module_big_fish::{EvaluateBigFishPublishReadinessCommand, evaluate_publish_readiness};
|
||||
|
||||
const INITIAL_BIG_FISH_CREATION_PROGRESS_PERCENT: u32 = 0;
|
||||
|
||||
@@ -552,6 +553,16 @@ pub(crate) fn compile_big_fish_draft_tx(
|
||||
.map_err(|error| format!("big_fish.draft_json 非法: {error}"))?
|
||||
.unwrap_or_else(|| compile_default_draft(&anchor_pack));
|
||||
let asset_slots = list_big_fish_asset_slots(ctx, &session.session_id);
|
||||
let readiness = evaluate_publish_readiness(
|
||||
EvaluateBigFishPublishReadinessCommand {
|
||||
session_id: session.session_id.clone(),
|
||||
owner_user_id: session.owner_user_id.clone(),
|
||||
draft: Some(draft.clone()),
|
||||
evaluated_at_micros: input.compiled_at_micros,
|
||||
},
|
||||
&asset_slots,
|
||||
)
|
||||
.map_err(|error| error.to_string())?;
|
||||
let coverage = build_asset_coverage(Some(&draft), &asset_slots);
|
||||
let compiled_at = Timestamp::from_micros_since_unix_epoch(input.compiled_at_micros);
|
||||
let reply = "第一版玩法草稿已编译完成,可以在结果页逐级生成主图、动作和场地背景。".to_string();
|
||||
@@ -568,12 +579,15 @@ pub(crate) fn compile_big_fish_draft_tx(
|
||||
asset_coverage_json: serialize_asset_coverage(&coverage)
|
||||
.map_err(|error| error.to_string())?,
|
||||
last_assistant_reply: Some(reply.clone()),
|
||||
publish_ready: coverage.publish_ready,
|
||||
publish_ready: readiness.readiness.publish_ready,
|
||||
play_count: session.play_count,
|
||||
created_at: session.created_at,
|
||||
updated_at: compiled_at,
|
||||
};
|
||||
replace_big_fish_session(ctx, &session, next_session);
|
||||
for event in readiness.events {
|
||||
emit_big_fish_publish_readiness_event(ctx, event)?;
|
||||
}
|
||||
|
||||
get_big_fish_session_tx(
|
||||
ctx,
|
||||
|
||||
Reference in New Issue
Block a user