feat(api): embed slots with ov replica and public feed
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,8 @@
|
||||
// 保留 likeTotal/countVersion 权威计数);photo.hidden/
|
||||
// deleted → photos_ov.visibility 置位(行不存在 = 从未复制即不可见,缺席
|
||||
// 即撤下语义);asset → banner 投影 albums_ov.bannerAssetKey(cover/logo
|
||||
// 仅推进版本,ov schema 无位);
|
||||
// 仅推进版本,ov schema 无位);slot-state(P4b Task 2)→ embed_slots_ov
|
||||
// 全量快照直投(albumPublicToken 弱关联相册、无依赖暂存,见 ③ 注);
|
||||
// ⑤ sync_state upsert appliedVersion(watermark=false 实体行;水位行预留)。
|
||||
// ⑥ 实时转发(Task 7):photo 事件**应用事务提交后**发布 OV_PHOTO_APPLIED
|
||||
// 进程内事件 → realtime 网关向相册房间广播契约 photo.* 消息(stale/
|
||||
@@ -40,6 +41,7 @@ import type {
|
||||
CategoryUpdatedPayload,
|
||||
PhotoPublishedPayload,
|
||||
PhotoVisibilityChangedPayload,
|
||||
SlotStateUpdatedPayload,
|
||||
} from '@photo/contracts';
|
||||
import type { Prisma } from '@photo/db-ov';
|
||||
// 值导入(非 import type):构造器注入的 design:paramtypes 依赖类引用,
|
||||
@@ -168,8 +170,11 @@ export class SyncInboxService {
|
||||
});
|
||||
return { outcome: 'stale' };
|
||||
}
|
||||
// ③ 依赖检查:非 album 事件须所属相册副本已存在,否则暂存。
|
||||
if (event.entityType !== 'album') {
|
||||
// ③ 依赖检查:非 album 事件须所属相册副本已存在,否则暂存。slot-state
|
||||
// 豁免:展示位副本以 albumPublicToken 弱关联相册(公开读时按 albums_ov
|
||||
// 现查,缺席=404 与相册下线同形),且解绑事件 albumId 为空串——相册行的
|
||||
// 到达顺序对副本正确性无影响,暂存反而会让解绑事件无限积压。
|
||||
if (event.entityType !== 'album' && event.entityType !== 'slot-state') {
|
||||
const album = await tx.albums_ov.findUnique({
|
||||
where: { albumId: event.albumId },
|
||||
select: { albumId: true },
|
||||
@@ -399,7 +404,31 @@ export class SyncInboxService {
|
||||
// cover/logo:ov schema 无投影位(YAGNI,schema 注释),仅推进版本账本。
|
||||
return undefined;
|
||||
}
|
||||
// slot-state 预留:受理即 applied(无投影),版本账本照常推进。
|
||||
// slot-state(P4b Task 2):全量快照直投 embed_slots_ov(版本单调已由 ②
|
||||
// 保证;同版本重断言同样走这里——整行替换幂等)。albumPublicToken null =
|
||||
// 解绑(公开端随即 404);无墓碑,下线是 enabled=false 的快照替换。
|
||||
if (event.entityType === 'slot-state') {
|
||||
const p = event.payload as unknown as SlotStateUpdatedPayload;
|
||||
await tx.embed_slots_ov.upsert({
|
||||
where: { slotToken: p.publicToken },
|
||||
create: {
|
||||
slotToken: p.publicToken,
|
||||
enabled: p.enabled,
|
||||
albumPublicToken: p.albumPublicToken ?? null,
|
||||
configVersion: p.configVersion,
|
||||
settings: p.settings as unknown as Prisma.InputJsonValue,
|
||||
entityVersion: event.entityVersion,
|
||||
},
|
||||
update: {
|
||||
enabled: p.enabled,
|
||||
albumPublicToken: p.albumPublicToken ?? null,
|
||||
configVersion: p.configVersion,
|
||||
settings: p.settings as unknown as Prisma.InputJsonValue,
|
||||
entityVersion: event.entityVersion,
|
||||
},
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user