Skip to content

Upload video media through PostSyncer's file endpoint - #243

Merged
HarunRRayhan merged 3 commits into
mainfrom
fix/video-upload-file-endpoint
Oct 26, 2026
Merged

HarunRRayhan merged 3 commits into
mainfrom
fix/video-upload-file-endpoint

Conversation

@HarunRRayhan

Copy link
Copy Markdown
Owner

Why

PostSyncer's POST /media/upload/url now stores no videos: it returns 200 {"media":[],"count_stored":0} for Drive video links and for a public non-Drive mp4. Images still import. Every video publish fails with "incomplete media upload response" (BV-109 blocked). The multipart file endpoint on upload.postsyncer.com works (135 MB mp4, 201 in 36 s).

What

  • PostsyncerClient::uploadFilesFromUrls(): streams each media URL to a temp file (sink), then uploads it to https://upload.postsyncer.com/api/v1/media/upload/file, one file per request, ids in URL order. Temp files are always deleted.
  • PublishVideoAction uses it for every video group (video and cover). Standalone posts are unchanged.
  • Safety: every file is downloaded before anything reaches PostSyncer. A download failure, an HTML page instead of media, an empty file, or a file over 500 MB is safe to retry. A definitive rejection of the first file is safe to retry. A lost or timed-out upload response, or any failure after a file was stored, stays uncertain.
  • Each file gets its own idempotency key (<key>:media:<index>), so one key never covers two files.
  • PublishVideoJob timeout 180 s to 900 s (overlap lock 1020 s), matching PublishPostJob, the worker's --timeout=900, and the 960 s retry_after/drain window. Download and upload calls use the existing 300 s HTTP timeout.

Tests

New client tests (order, upload host, multipart, per-file keys, uncertain on connection error, safe on first-file 422, unsafe after a stored file, download failure sends nothing, HTML page, size cap, temp cleanup). Video action, API, and reconcile tests moved to the file endpoint.

Generated with Claude Code

PostSyncer's URL import now stores no videos (200, count_stored 0), so video
groups download each media URL to a temp file and upload it to
upload.postsyncer.com/api/v1/media/upload/file, keeping URL order.
Download failures, the 500 MB cap, and a rejection before any file is stored
are safe to retry; a lost upload response stays uncertain. PublishVideoJob's
timeout goes from 180 to 900 seconds to fit the transfers.
… cap

Every download hop must be an https Google Drive host that passes
PublicUrlGuard, with DNS pinned; redirects are followed manually (max 5).
Content-Length or streamed bytes over 500 MB abort the download. A failure
after a file was stored names the stored media ids.
Guzzle 8 rejects raw CURLOPT_PROGRESSFUNCTION in the curl option, so the
cap stays on Guzzle's progress option, which aborts when the callback
returns true. A test streams from a local server through Guzzle's cURL
handler and checks the transfer stops before the full file arrives.
@HarunRRayhan
HarunRRayhan merged commit d2a4011 into main Oct 26, 2026
4 checks passed
@HarunRRayhan
HarunRRayhan deleted the fix/video-upload-file-endpoint branch October 26, 2026 06:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant