修复重复键问题

This commit is contained in:
2026-04-24 10:58:10 +08:00
parent 61f999eba9
commit 091accae9b
4 changed files with 33 additions and 16 deletions

View File

@@ -1,6 +1,7 @@
# AGENTS.md
## 项目约束
- 在修改server-rs的内容时不要去兼容server-node中的任何内容只允许参考以及把server-node中未迁移到server-rs的内容迁移过来
- 代码需要有完善的中文注释
- 在落地工程修改前检查是否有详细指导本次落地的文档,若没有文档或文档的完善程度仍有落地过程中编码级别的歧义优先优化文档后落地工程迭代。
- 对工程的修改不仅要落地到代码更面还要更改对应文档若没有生成新的文档文档统一存在doc目录中

View File

@@ -261,6 +261,12 @@
| `created_at` | `Timestamp` | 是 | 创建时间 |
| `updated_at` | `Timestamp` | 是 | 更新时间 |
### 主键约束
1. `card_id` 是 SpacetimeDB 表级全局主键,不能只使用 `world-foundation` 这类跨会话固定值。
2. Agent 自动生成的世界底稿卡统一使用 `custom-world:{session_id}:world-foundation`,确保同一会话内稳定 upsert、不同会话间不会发生唯一键冲突。
3. 不保留历史 `world-foundation` 主键兼容逻辑;线上旧脏数据如需清理,应通过一次性运维脚本处理,不进入 reducer 主链。
### 索引
1. `session_id`

View File

@@ -2770,7 +2770,13 @@ fn upsert_world_foundation_card(
draft_profile: &JsonMap<String, JsonValue>,
updated_at_micros: i64,
) -> Result<(), String> {
let card_id = "world-foundation".to_string();
let card_id = build_world_foundation_card_id(session_id);
let existing_card = ctx
.db
.custom_world_draft_card()
.card_id()
.find(&card_id)
.filter(|row| row.session_id == session_id);
let title = read_optional_text_field(draft_profile, &["name", "title"])
.unwrap_or_else(|| "世界底稿".to_string());
let subtitle = read_optional_text_field(draft_profile, &["subtitle"]).unwrap_or_default();
@@ -2792,13 +2798,7 @@ fn upsert_world_foundation_card(
"warningMessages": [],
}))?;
if let Some(existing) = ctx
.db
.custom_world_draft_card()
.card_id()
.find(&card_id)
.filter(|row| row.session_id == session_id)
{
if let Some(existing) = existing_card {
replace_custom_world_draft_card(
ctx,
&existing,
@@ -2849,6 +2849,11 @@ fn upsert_world_foundation_card(
Ok(())
}
fn build_world_foundation_card_id(session_id: &str) -> String {
// `custom_world_draft_card.card_id` 是全局主键,世界底稿卡必须带上会话维度,避免多会话写入时触发唯一键冲突。
format!("custom-world:{session_id}:world-foundation")
}
fn sync_session_draft_profile_from_card_update(
session: &CustomWorldAgentSession,
card: &CustomWorldDraftCard,

View File

@@ -4144,7 +4144,13 @@ fn upsert_world_foundation_card(
draft_profile: &JsonMap<String, JsonValue>,
updated_at_micros: i64,
) -> Result<(), String> {
let card_id = "world-foundation".to_string();
let card_id = build_world_foundation_card_id(session_id);
let existing_card = ctx
.db
.custom_world_draft_card()
.card_id()
.find(&card_id)
.filter(|row| row.session_id == session_id);
let title = read_optional_text_field(draft_profile, &["name", "title"])
.unwrap_or_else(|| "世界底稿".to_string());
let subtitle = read_optional_text_field(draft_profile, &["subtitle"]).unwrap_or_default();
@@ -4166,13 +4172,7 @@ fn upsert_world_foundation_card(
"warningMessages": [],
}))?;
if let Some(existing) = ctx
.db
.custom_world_draft_card()
.card_id()
.find(&card_id)
.filter(|row| row.session_id == session_id)
{
if let Some(existing) = existing_card {
replace_custom_world_draft_card(
ctx,
&existing,
@@ -4223,6 +4223,11 @@ fn upsert_world_foundation_card(
Ok(())
}
fn build_world_foundation_card_id(session_id: &str) -> String {
// `custom_world_draft_card.card_id` 是全局主键,世界底稿卡必须带上会话维度,避免多会话写入时触发唯一键冲突。
format!("custom-world:{session_id}:world-foundation")
}
fn sync_session_draft_profile_from_card_update(
session: &CustomWorldAgentSession,
card: &CustomWorldDraftCard,