From a3c7c3d76a19862e50aab74b4ffb8790d9dbcef8 Mon Sep 17 00:00:00 2001 From: Maurice Date: Mon, 9 Nov 2026 12:25:40 +0100 Subject: [PATCH] fix(memories): mark the Synology lookups and repair as independent writes for the transaction gate Each photo's write follows its own network lookup, the repair's marker only records that the pass ran, and a lookup may renew the Synology session on its own; none of these can share one transaction. --- server/src/nest/memories/synology-capture-repair.job.ts | 7 +++++++ server/src/nest/memories/synology.service.ts | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/server/src/nest/memories/synology-capture-repair.job.ts b/server/src/nest/memories/synology-capture-repair.job.ts index 0d0569883..6050ffdc5 100644 --- a/server/src/nest/memories/synology-capture-repair.job.ts +++ b/server/src/nest/memories/synology-capture-repair.job.ts @@ -54,6 +54,8 @@ export class SynologyCaptureRepairJob implements OnApplicationBootstrap { /** * The pages after `after`, one after the other: each page's lookups run at * once, held to a few per library by the backfill's slots. + * + * @txIndependent each photo's write follows its own lookup in the owner's library and stands on its own. */ private async walk(after: number): Promise<{ changed: number; failed: number }> { const page = await this.trekPhotos.listByProviderAfter(PROVIDER, after, PAGE); @@ -66,6 +68,11 @@ export class SynologyCaptureRepairJob implements OnApplicationBootstrap { }; } + /** + * One pass, then the marker of how far it got. + * + * @txIndependent the marker follows a pass of network lookups and records only that the pass ran. + */ async runOnce(): Promise { try { if ((await this.settings.getAppSetting(SYNOLOGY_CAPTURE_REPAIR_DONE_KEY)) !== null) return; diff --git a/server/src/nest/memories/synology.service.ts b/server/src/nest/memories/synology.service.ts index 362b133f6..1ceb0c60f 100644 --- a/server/src/nest/memories/synology.service.ts +++ b/server/src/nest/memories/synology.service.ts @@ -724,6 +724,12 @@ export class SynologyService { }); } + /** + * The photo's own details: the item of its unit, and the next item only when + * the library answered with another photo there (#3019). + * + * @txIndependent each lookup may renew the Synology session first; that write stands on its own. + */ async getSynologyAssetInfo( userId: number, photoId: string,