From d763be6322a97c3ba389c9e3bb5f9580eb31a704 Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Mon, 4 May 2026 14:08:15 +0200 Subject: [PATCH] fix: prevent ENOENT on scheduled reel publishing when local file deleted early - facebook.ts: use resolvePublicUrl + getMediaBuffer for reels so missing local files fall back to HTTP fetch. - scheduler.ts: only delete local video files after the last pending scheduled post for that postId is published. Co-Authored-By: Claude Opus 4.7 --- server/services/facebook.ts | 8 +++----- server/services/scheduler.ts | 12 +++++++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/server/services/facebook.ts b/server/services/facebook.ts index 5ce6fca..ab89979 100644 --- a/server/services/facebook.ts +++ b/server/services/facebook.ts @@ -72,11 +72,9 @@ export class FacebookService { throw new Error('Reels require a video media'); } - // Upload video bytes directly — Facebook cannot fetch local/Docker URLs - const localPath = videoMedia.originalUrl.startsWith('/') - ? path.join(process.cwd(), videoMedia.originalUrl) - : videoMedia.originalUrl; - const nodeBuffer = await fs.promises.readFile(localPath); + // Use public URL so getMediaBuffer can fetch via HTTP if local file is missing + const publicUrl = resolvePublicUrl(videoMedia.originalUrl); + const nodeBuffer = await this.getMediaBuffer(publicUrl); return await this.publishVideoFromBuffer(page, nodeBuffer, post.content); } else { // Default to feed diff --git a/server/services/scheduler.ts b/server/services/scheduler.ts index d9e2364..36b88df 100644 --- a/server/services/scheduler.ts +++ b/server/services/scheduler.ts @@ -125,12 +125,18 @@ export class SchedulerService { status: "published", }); - // Delete local video files immediately after successful publishing + // Delete local video files only when no other unpublished scheduled posts reference them for (const mediaItem of mediaList) { if (mediaItem.type === 'video' && mediaItem.cloudinaryPublicId) { try { - await storageService.deleteMedia(mediaItem.cloudinaryPublicId, mediaItem.userId, 'video'); - console.log(`[Scheduler] Deleted local video file for media ${mediaItem.id}`); + const remainingScheduled = await storage.getScheduledPostsByPost(post.id); + const hasPending = remainingScheduled.some(sp => !sp.publishedAt); + if (!hasPending) { + await storageService.deleteMedia(mediaItem.cloudinaryPublicId, mediaItem.userId, 'video'); + console.log(`[Scheduler] Deleted local video file for media ${mediaItem.id}`); + } else { + console.log(`[Scheduler] Kept local video file for media ${mediaItem.id} (pending scheduled posts still exist)`); + } } catch (err) { console.warn(`[Scheduler] Failed to delete local video file for media ${mediaItem.id}:`, err); }