fix(acquisition): 评估路径补建收录版本时锁订阅行;规则 API 测试按新建订阅自带默认版本更新

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-03 23:32:10 +08:00
1 parent df1a9bc1a9
commit 0bbf5885aa
2 files changed
+13 -5

No files matched your search

@@ -233,17 +233,24 @@ export async function createSlotsFromTemplates(
/** 追踪中的订阅里没有自己收录版本的,逐个补建;返回是否建了 */
async function backfillSubscriptionSlots(
exec: Exec,
db: AoDeps["ctx"]["db"],
subs: readonly SubscriptionRow[],
slots: readonly Pick<AcquisitionSlotRow, "subscription_id">[],
): Promise<boolean> {
let made = 0;
for (const s of subs)
if (s.media_entity_id && !slots.some((x) => x.subscription_id === s.id))
made += await ensureSubscriptionSlot(exec, s);
if (s.media_entity_id && !slots.some((x) => x.subscription_id === s.id)) made += await ensureSlotLocked(db, s);
return made > 0;
}
/** 评估路径上补建:锁订阅行,免得并发的两次评估各建一个 */
function ensureSlotLocked(db: AoDeps["ctx"]["db"], sub: SubscriptionRow): Promise<number> {
return db.transaction().execute(async (trx) => {
await trx.selectFrom("subscription").select("id").where("id", "=", sub.id).forUpdate().execute();
return ensureSubscriptionSlot(trx, sub);
});
}
/** 订阅没有收录策略模板时的隐式缺省收录版本:无硬条件,表单的质量预设 / 包含排除随后由订阅参数写入 */
export const DEFAULT_SLOT_TEMPLATE: SlotTemplate = { name: "默认版本" };
@@ -377,7 +384,7 @@ async function reevaluate(c: Ctx, input: EvaluateInput): Promise<EvaluateOutcome
sub = sid ? await db.selectFrom("subscription").selectAll().where("id", "=", sid).executeTakeFirst() : undefined;
} else if (input.subscriptionId) {
sub = await db.selectFrom("subscription").selectAll().where("id", "=", input.subscriptionId).executeTakeFirst();
if (sub && (TRACKING_SUB_STATUSES as readonly string[]).includes(sub.status)) await ensureSubscriptionSlot(db, sub);
if (sub && (TRACKING_SUB_STATUSES as readonly string[]).includes(sub.status)) await ensureSlotLocked(db, sub);
if (sub)
focus = await db
.selectFrom("acquisition_slot")