mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-21 22:46:32 +00:00
fix(docsync): stop a push from stealing another file's pairing
Papra answers a push of bytes it already holds with the document that has them. Two trip files with the same content therefore pushed to one document, and the unique index on (link_id, remote_id) aborted that run and every run after it with a constraint error. The pairing now stays with the file that owns it and the second file is recorded as a conflict. Also in this pass: - Paperless no longer adopts a same-bytes document that lacks the scope's tag when a consume outlives the poll budget; that document belongs to someone else's filing and delete-through would have trashed it. - The pull path writes the file row, the retirement of the copy it replaces and the pairing in one transaction, and announces them only once committed. - PATCH links stops accepting remoteRootId/remoteRootPath, which it read and silently dropped. - The MCP sync tool clears shelved items before running, as the REST route does.
This commit is contained in:
@@ -100,14 +100,20 @@ export class DocSyncWebhookController implements OnModuleDestroy {
|
||||
* up again when the timer fires, so a binding switched off or deleted in the
|
||||
* meantime does not get one last run out of a stale row.
|
||||
*/
|
||||
private schedule(linkId: number, reload: () => ReturnType<DocSyncConfigService['getLink']>): void {
|
||||
private schedule(linkId: number, reload: () => ReturnType<DocSyncConfigService['getLink']>, isRetry = false): void {
|
||||
if (this.pending.has(linkId)) return;
|
||||
const timer = setTimeout(() => {
|
||||
this.pending.delete(linkId);
|
||||
const fresh = reload();
|
||||
if (!fresh || fresh.sync_enabled !== 1) return;
|
||||
if (!this.syncIsOn()) return;
|
||||
void this.sync.syncLink(fresh);
|
||||
void this.sync.syncLink(fresh).then((res) => {
|
||||
// A run that was already in flight answers `busy`, and the changes this
|
||||
// nudge was about may have landed after that run read the folder. Ask
|
||||
// again once rather than waiting out a whole poll interval — once, and
|
||||
// only for `busy`, so this cannot become a loop.
|
||||
if (res?.state === 'busy' && !isRetry) this.schedule(linkId, reload, true);
|
||||
});
|
||||
}, WEBHOOK_NUDGE_DEBOUNCE_SECONDS * 1000);
|
||||
// A pending nudge must not hold the process open at shutdown.
|
||||
if (typeof timer.unref === 'function') timer.unref();
|
||||
|
||||
Reference in New Issue
Block a user