feat(worker): watermark versioning with atomic history regeneration
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
// bootstrap/reconcile 同一出口);worker publish.service 的首次发布载荷来自
|
||||
// 流水线内存值(同构不同源),保持不动。
|
||||
import { HttpStatus } from '@nestjs/common';
|
||||
import { ErrorCodes } from '@photo/contracts';
|
||||
import { ErrorCodes, buildAlbumUpdatedPayloadCore } from '@photo/contracts';
|
||||
import type {
|
||||
AlbumUpdatedPayload,
|
||||
AssetUpdatedPayload,
|
||||
@@ -31,6 +31,8 @@ type AlbumRow = Pick<
|
||||
| 'publicEnabled'
|
||||
| 'downloadEnabled'
|
||||
| 'originalDownloadEnabled'
|
||||
| 'watermarkEnabled'
|
||||
| 'watermarkEffectiveVersion'
|
||||
| 'defaultLocale'
|
||||
| 'timezone'
|
||||
| 'startAt'
|
||||
@@ -52,6 +54,8 @@ type PhotoVariantRow = Prisma.photo_variantsGetPayload<
|
||||
|
||||
/**
|
||||
* album.updated 载荷:albums_ov 展示所需标量 + 翻译全集(locale 升序)。
|
||||
* P4a Task 3 起标量全集(含水印副本位)的构建收敛到 contracts 的共享实现
|
||||
* (worker 完成事务同用,见 buildAlbumUpdatedPayloadCore);本包装仅叠加
|
||||
* categories 可选参数:仅 bootstrap/reconcile 快照事件传入(ov 整体替换
|
||||
* albums_ov.categories 的收敛原语,见 contracts events.ts 注释);业务事务内
|
||||
* 增量事件不传(分类元素归 category.* 事件管)。输出按 (sortOrder, id) 升序
|
||||
@@ -62,48 +66,26 @@ export function buildAlbumUpdatedPayload(
|
||||
translations: AlbumTranslationRow[],
|
||||
categories?: AlbumCategoryInput[],
|
||||
): AlbumUpdatedPayload {
|
||||
return {
|
||||
albumId: album.id,
|
||||
publicToken: album.publicToken,
|
||||
status: album.status,
|
||||
uploadEnabled: album.uploadEnabled,
|
||||
publicEnabled: album.publicEnabled,
|
||||
downloadEnabled: album.downloadEnabled,
|
||||
originalDownloadEnabled: album.originalDownloadEnabled,
|
||||
defaultLocale: album.defaultLocale,
|
||||
timezone: album.timezone,
|
||||
startAt: album.startAt.toISOString(),
|
||||
endAt: album.endAt === null ? null : album.endAt.toISOString(),
|
||||
translations: [...translations]
|
||||
.sort((a, b) => (a.locale < b.locale ? -1 : 1))
|
||||
.map((t) => ({
|
||||
locale: t.locale,
|
||||
title: t.title,
|
||||
description: t.description,
|
||||
venue: t.venue,
|
||||
address: t.address,
|
||||
})),
|
||||
...(categories === undefined
|
||||
? {}
|
||||
: {
|
||||
categories: [...categories]
|
||||
.sort((a, b) =>
|
||||
a.category.sortOrder !== b.category.sortOrder
|
||||
? a.category.sortOrder - b.category.sortOrder
|
||||
: a.category.id < b.category.id
|
||||
? -1
|
||||
: 1,
|
||||
)
|
||||
.map(({ category, translations: categoryTranslations }) => ({
|
||||
id: category.id,
|
||||
sortOrder: category.sortOrder,
|
||||
translations: [...categoryTranslations]
|
||||
.sort((a, b) => (a.locale < b.locale ? -1 : 1))
|
||||
.map((t) => ({ locale: t.locale, name: t.name })),
|
||||
})),
|
||||
}),
|
||||
entityVersion: album.entityVersion,
|
||||
};
|
||||
const payload = buildAlbumUpdatedPayloadCore(album, translations);
|
||||
if (categories === undefined) {
|
||||
return payload;
|
||||
}
|
||||
payload.categories = [...categories]
|
||||
.sort((a, b) =>
|
||||
a.category.sortOrder !== b.category.sortOrder
|
||||
? a.category.sortOrder - b.category.sortOrder
|
||||
: a.category.id < b.category.id
|
||||
? -1
|
||||
: 1,
|
||||
)
|
||||
.map(({ category, translations: categoryTranslations }) => ({
|
||||
id: category.id,
|
||||
sortOrder: category.sortOrder,
|
||||
translations: [...categoryTranslations]
|
||||
.sort((a, b) => (a.locale < b.locale ? -1 : 1))
|
||||
.map((t) => ({ locale: t.locale, name: t.name })),
|
||||
}));
|
||||
return payload;
|
||||
}
|
||||
|
||||
/** 快照 categories 参数形状:分类行 + 该分类的翻译行(见函数注释)。 */
|
||||
|
||||
Reference in New Issue
Block a user