perf: cache public gallery views

This commit is contained in:
kdletters
2026-05-17 01:19:12 +08:00
parent d9c8473504
commit 81fe3dcf28
39 changed files with 2124 additions and 298 deletions

View File

@@ -1708,6 +1708,33 @@ pub(crate) fn map_big_fish_works_procedure_result(
})
}
pub(crate) fn map_big_fish_gallery_view_row(
row: BigFishWorkSummarySnapshot,
recent_play_count_7d: u32,
) -> BigFishWorkSummaryRecord {
BigFishWorkSummaryRecord {
work_id: row.work_id,
source_session_id: row.source_session_id,
owner_user_id: row.owner_user_id,
title: row.title,
subtitle: row.subtitle,
summary: row.summary,
cover_image_src: row.cover_image_src,
status: row.status,
updated_at_micros: row.updated_at_micros,
published_at_micros: row.published_at_micros,
publish_ready: row.publish_ready,
level_count: row.level_count,
level_main_image_ready_count: row.level_main_image_ready_count,
level_motion_ready_count: row.level_motion_ready_count,
background_ready: row.background_ready,
play_count: row.play_count,
remix_count: row.remix_count,
like_count: row.like_count,
recent_play_count_7d,
}
}
pub(crate) fn map_big_fish_run_procedure_result(
result: BigFishRunProcedureResult,
) -> Result<BigFishRuntimeRunRecord, SpacetimeClientError> {
@@ -3071,6 +3098,16 @@ pub(crate) fn map_puzzle_anchor_pack(snapshot: DomainPuzzleAnchorPack) -> Puzzle
}
}
fn map_puzzle_anchor_pack_row(snapshot: PuzzleAnchorPack) -> PuzzleAnchorPackRecord {
PuzzleAnchorPackRecord {
theme_promise: map_puzzle_anchor_item_row(snapshot.theme_promise),
visual_subject: map_puzzle_anchor_item_row(snapshot.visual_subject),
visual_mood: map_puzzle_anchor_item_row(snapshot.visual_mood),
composition_hooks: map_puzzle_anchor_item_row(snapshot.composition_hooks),
tags_and_forbidden: map_puzzle_anchor_item_row(snapshot.tags_and_forbidden),
}
}
pub(crate) fn map_puzzle_anchor_item(snapshot: DomainPuzzleAnchorItem) -> PuzzleAnchorItemRecord {
PuzzleAnchorItemRecord {
key: snapshot.key,
@@ -3080,6 +3117,15 @@ pub(crate) fn map_puzzle_anchor_item(snapshot: DomainPuzzleAnchorItem) -> Puzzle
}
}
fn map_puzzle_anchor_item_row(snapshot: PuzzleAnchorItem) -> PuzzleAnchorItemRecord {
PuzzleAnchorItemRecord {
key: snapshot.key,
label: snapshot.label,
value: snapshot.value,
status: format_puzzle_anchor_status(snapshot.status).to_string(),
}
}
pub(crate) fn map_puzzle_result_draft(
snapshot: DomainPuzzleResultDraft,
) -> PuzzleResultDraftRecord {
@@ -3142,6 +3188,28 @@ pub(crate) fn map_puzzle_draft_level(snapshot: DomainPuzzleDraftLevel) -> Puzzle
}
}
fn map_puzzle_draft_level_row(snapshot: PuzzleDraftLevel) -> PuzzleDraftLevelRecord {
PuzzleDraftLevelRecord {
level_id: snapshot.level_id,
level_name: snapshot.level_name,
picture_description: snapshot.picture_description,
picture_reference: snapshot.picture_reference,
ui_background_prompt: snapshot.ui_background_prompt,
ui_background_image_src: snapshot.ui_background_image_src,
ui_background_image_object_key: snapshot.ui_background_image_object_key,
background_music: snapshot.background_music.map(map_puzzle_audio_asset_row),
candidates: snapshot
.candidates
.into_iter()
.map(map_puzzle_generated_image_candidate_row)
.collect(),
selected_candidate_id: snapshot.selected_candidate_id,
cover_image_src: snapshot.cover_image_src,
cover_asset_id: snapshot.cover_asset_id,
generation_status: snapshot.generation_status,
}
}
pub(crate) fn map_puzzle_audio_asset(
asset: module_puzzle::PuzzleAudioAsset,
) -> PuzzleAudioAssetRecord {
@@ -3157,6 +3225,19 @@ pub(crate) fn map_puzzle_audio_asset(
}
}
fn map_puzzle_audio_asset_row(asset: PuzzleAudioAsset) -> PuzzleAudioAssetRecord {
PuzzleAudioAssetRecord {
task_id: asset.task_id,
provider: asset.provider,
asset_object_id: asset.asset_object_id,
asset_kind: asset.asset_kind,
audio_src: asset.audio_src,
prompt: asset.prompt,
title: asset.title,
updated_at: asset.updated_at,
}
}
pub(crate) fn map_puzzle_creator_intent(
snapshot: DomainPuzzleCreatorIntent,
) -> PuzzleCreatorIntentRecord {
@@ -3186,6 +3267,20 @@ pub(crate) fn map_puzzle_generated_image_candidate(
}
}
fn map_puzzle_generated_image_candidate_row(
snapshot: PuzzleGeneratedImageCandidate,
) -> PuzzleGeneratedImageCandidateRecord {
PuzzleGeneratedImageCandidateRecord {
candidate_id: snapshot.candidate_id,
image_src: snapshot.image_src,
asset_id: snapshot.asset_id,
prompt: snapshot.prompt,
actual_prompt: snapshot.actual_prompt,
source_type: snapshot.source_type,
selected: snapshot.selected,
}
}
pub(crate) fn map_puzzle_agent_message_snapshot(
snapshot: DomainPuzzleAgentMessageSnapshot,
) -> PuzzleAgentMessageRecord {
@@ -3298,6 +3393,32 @@ fn map_match3d_work_snapshot(snapshot: Match3DWorkJsonRecord) -> Match3DWorkProf
}
}
pub(crate) fn map_match3d_gallery_view_row(row: Match3DGalleryViewRow) -> Match3DWorkProfileRecord {
Match3DWorkProfileRecord {
work_id: row.profile_id.clone(),
profile_id: row.profile_id,
owner_user_id: row.owner_user_id,
source_session_id: empty_string_to_none(row.source_session_id),
author_display_name: row.author_display_name,
game_name: row.game_name,
theme_text: row.theme_text,
summary: row.summary_text,
tags: row.tags,
cover_image_src: empty_string_to_none(row.cover_image_src),
cover_asset_id: empty_string_to_none(row.cover_asset_id),
reference_image_src: row.reference_image_src,
clear_count: row.clear_count,
difficulty: row.difficulty,
publication_status: normalize_match3d_publication_status(&row.publication_status)
.to_string(),
play_count: row.play_count,
updated_at: format_timestamp_micros(row.updated_at_micros),
published_at: row.published_at_micros.map(format_timestamp_micros),
publish_ready: row.publish_ready,
generated_item_assets_json: row.generated_item_assets_json,
}
}
fn map_match3d_run_json(run_json: String) -> Result<Match3DRunRecord, SpacetimeClientError> {
let run = serde_json::from_str::<Match3DRunJsonRecord>(&run_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("match3d run_json 非法: {error}"))
@@ -3523,6 +3644,44 @@ fn map_square_hole_work_snapshot(
}
}
pub(crate) fn map_square_hole_gallery_view_row(
row: SquareHoleGalleryViewRow,
) -> SquareHoleWorkProfileRecord {
SquareHoleWorkProfileRecord {
work_id: row.work_id,
profile_id: row.profile_id,
owner_user_id: row.owner_user_id,
source_session_id: empty_string_to_none(row.source_session_id),
author_display_name: row.author_display_name,
game_name: row.game_name,
theme_text: row.theme_text,
twist_rule: row.twist_rule,
summary: row.summary_text,
tags: row.tags,
cover_image_src: empty_string_to_none(row.cover_image_src),
background_prompt: row.background_prompt,
background_image_src: empty_string_to_none(row.background_image_src),
shape_options: row
.shape_options
.into_iter()
.map(map_square_hole_shape_option_snapshot)
.collect(),
hole_options: row
.hole_options
.into_iter()
.map(map_square_hole_hole_option_snapshot)
.collect(),
shape_count: row.shape_count,
difficulty: row.difficulty,
publication_status: normalize_square_hole_publication_status(&row.publication_status)
.to_string(),
play_count: row.play_count,
updated_at: format_timestamp_micros(row.updated_at_micros),
published_at: row.published_at_micros.map(format_timestamp_micros),
publish_ready: row.publish_ready,
}
}
fn map_square_hole_run_json(run_json: String) -> Result<SquareHoleRunRecord, SpacetimeClientError> {
let run = serde_json::from_str::<SquareHoleRunJsonRecord>(&run_json).map_err(|error| {
SpacetimeClientError::Runtime(format!("square hole run_json 非法: {error}"))
@@ -3612,6 +3771,31 @@ fn map_square_hole_hole_option(
}
}
fn map_square_hole_shape_option_snapshot(
snapshot: SquareHoleShapeOptionSnapshot,
) -> SquareHoleShapeOptionRecord {
SquareHoleShapeOptionRecord {
option_id: snapshot.option_id,
shape_kind: snapshot.shape_kind,
label: snapshot.label,
target_hole_id: snapshot.target_hole_id,
image_prompt: snapshot.image_prompt,
image_src: empty_string_to_none(snapshot.image_src),
}
}
fn map_square_hole_hole_option_snapshot(
snapshot: SquareHoleHoleOptionSnapshot,
) -> SquareHoleHoleOptionRecord {
SquareHoleHoleOptionRecord {
hole_id: snapshot.hole_id,
hole_kind: snapshot.hole_kind,
label: snapshot.label,
image_prompt: snapshot.image_prompt,
image_src: empty_string_to_none(snapshot.image_src),
}
}
fn map_square_hole_feedback_snapshot(
snapshot: SquareHoleDropFeedbackJsonRecord,
) -> SquareHoleDropFeedbackRecord {
@@ -3722,6 +3906,31 @@ fn map_visual_novel_work_snapshot(
}
}
pub(crate) fn map_visual_novel_gallery_view_row(
row: VisualNovelGalleryViewRow,
) -> VisualNovelWorkProfileRecord {
VisualNovelWorkProfileRecord {
work_id: row.work_id,
profile_id: row.profile_id,
owner_user_id: row.owner_user_id,
source_session_id: row.source_session_id,
author_display_name: row.author_display_name,
work_title: row.work_title,
work_description: row.work_description,
tags: row.tags,
cover_image_src: row.cover_image_src,
source_asset_ids: row.source_asset_ids,
// 中文注释:公开列表 view 不暴露完整 draft详情页仍通过 detail procedure 读取。
draft: serde_json::Value::Null,
publication_status: row.publication_status,
publish_ready: row.publish_ready,
play_count: row.play_count,
created_at: format_timestamp_micros(row.created_at_micros),
updated_at: format_timestamp_micros(row.updated_at_micros),
published_at: row.published_at_micros.map(format_timestamp_micros),
}
}
fn map_visual_novel_run_snapshot(snapshot: VisualNovelRunJsonRecord) -> VisualNovelRunRecord {
VisualNovelRunRecord {
run_id: snapshot.run_id,
@@ -3790,6 +3999,22 @@ fn normalize_match3d_stage(value: &str) -> &str {
}
}
fn format_puzzle_publication_status(value: PuzzlePublicationStatus) -> &'static str {
match value {
PuzzlePublicationStatus::Draft => "draft",
PuzzlePublicationStatus::Published => "published",
}
}
fn format_puzzle_anchor_status(value: PuzzleAnchorStatus) -> &'static str {
match value {
PuzzleAnchorStatus::Missing => "missing",
PuzzleAnchorStatus::Inferred => "inferred",
PuzzleAnchorStatus::Confirmed => "confirmed",
PuzzleAnchorStatus::Locked => "locked",
}
}
fn normalize_match3d_publication_status(value: &str) -> &str {
match value {
"Draft" | "draft" => "draft",
@@ -3951,6 +4176,40 @@ pub(crate) fn map_puzzle_work_profile(
}
}
pub(crate) fn map_puzzle_work_profile_row(snapshot: PuzzleWorkProfile) -> PuzzleWorkProfileRecord {
PuzzleWorkProfileRecord {
work_id: snapshot.work_id,
profile_id: snapshot.profile_id,
owner_user_id: snapshot.owner_user_id,
source_session_id: snapshot.source_session_id,
author_display_name: snapshot.author_display_name,
work_title: snapshot.work_title,
work_description: snapshot.work_description,
level_name: snapshot.level_name,
summary: snapshot.summary,
theme_tags: snapshot.theme_tags,
cover_image_src: snapshot.cover_image_src,
cover_asset_id: snapshot.cover_asset_id,
publication_status: format_puzzle_publication_status(snapshot.publication_status)
.to_string(),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
published_at: snapshot.published_at_micros.map(format_timestamp_micros),
play_count: snapshot.play_count,
remix_count: snapshot.remix_count,
like_count: snapshot.like_count,
recent_play_count_7d: snapshot.recent_play_count_7_d,
point_incentive_total_half_points: snapshot.point_incentive_total_half_points,
point_incentive_claimed_points: snapshot.point_incentive_claimed_points,
publish_ready: snapshot.publish_ready,
anchor_pack: map_puzzle_anchor_pack_row(snapshot.anchor_pack),
levels: snapshot
.levels
.into_iter()
.map(map_puzzle_draft_level_row)
.collect(),
}
}
pub(crate) fn map_puzzle_run_snapshot(snapshot: DomainPuzzleRunSnapshot) -> PuzzleRunRecord {
PuzzleRunRecord {
run_id: snapshot.run_id,