This document describes the execution logic and state rules of the TaskService.saveMetadata method. As the entrypoint of the synchronization pipeline, this method handles validation, metadata deduplication, change detection, and S3 physical asset soft-delete scheduling before files are actually downloaded.
When an external synchronization payload is sent to /api/task/create, the backend executes saveMetadata for each post synchronously and atomically.
By comparing the incoming payload with existing database states, the method determines if it needs to trigger background download tasks (via the PostgreSQL DB Queue engine and in-process JobRunner). If all media URLs and metadata match the database exactly, the method returns skipUpdate: true, skipping background unit enqueueing and reducing network overhead.
graph TD
Start([Start saveMetadata]) --> Step1[1. Author Sync & Deduplication]
Step1 --> Step2[2. Post Sync & Deduplication]
Step2 --> Step3[3. Media & Track Change Detection]
Step3 --> Step3_1[3.1 Soft Delete Orphaned Media & Tracks]
Step3_1 --> Step3_2[3.2 Sync Tracks & File URL Diff Checks]
Step3_2 --> Step3_3[3.3 Relational Tag Mapping]
Step3_3 --> Step4[4. Author Avatar Check]
Step4 --> Step5[5. Enqueue POST_PROCESS Task & Units]
Step5 --> End([Return postId, authorId, skipUpdate])
- Matching: Queries the
Authortable using the author's platform IDeid,platform, and the targetlibrary_id. - Insert: If not found, generates a new author UUID and writes the nickname, platform, signature, and metadata.
- Update: If the author exists but the nickname has changed, updates the record in the database. Resets
delete_status = DeleteStatus.ACTIVEif previously deleted.
- Matching: Queries the
Posttable usingeidandsourceplatform. - Exists (Update Path):
- Compares the incoming post details with the database record.
- Updates the post's title, body description, raw tags array, author reference, and total media counts.
- Syncs relational tags using
syncEntityTags(interfacing with theTagandPostTagtables).
- Does Not Exist (Insert Path):
- Inserts a new
Postrecord withsync_statusset toPENDINGand binds the transaction metadata. SetshasPendingTasks = true.
- Inserts a new
Iterates over the incoming media array and matches every item by a non-empty, stable external_id. If the caller cannot provide a stable identity, the server rejects the synchronization request instead of guessing from an array index or sort_order:
If a post's media list changes on the source platform (e.g., a photo is deleted from a post):
- Identify Orphans: Finds existing database
Mediaitems for this post that are missing from the incoming payload. - Soft Delete: In one transaction, marks obsolete
Media, associatedTrack, and their ownedFilerecords asDELETEDand recordsdelete_time. Physical S3 objects remain until the later purge task. - Sets
hasPendingTasks = true.
For each active or new media item:
- Insert Media: If not found, inserts a new
Mediarow with its status set toPENDING. - Track Match: Compares the incoming tracks (specifying type, purpose, and priority) with existing active
Trackrecords. - Change Detection:
- Checks if any incoming track has a different
source_url,is_originalsetting,qualitytier, or modified metadata compared to the database. - On Track URL / Setting Change:
- Marks the old associated
Filerecord (if any) asDELETEDand records thedelete_time. - Sets the
Trackstatus toPENDINGand clears out itsfile_idandlast_error. - Sets
hasPendingTasks = trueto signal that background download and verification are required.
- Marks the old associated
- Checks if any incoming track has a different
- Obsolete Tracks Cleanup: Any active
Trackrecords in the database that are missing from the incoming payload are marked asDELETED, and their owned File records are marked asDELETEDin the same transaction. Physical objects are handled by the purge task.
- Calls
syncEntityTagsto parse and sanitize tags. - For new tags, writes candidate records to the
Tagtable (status = TagStatus.CANDIDATE). - Maintains mappings in the
PostTagandMediaTagtables.
- Checks if the author has an active avatar. If the payload supplies
avatar_file_urlbutavatar_file_idis empty, marks the avatar task for download and setshasPendingTasks = true.
- If
hasPendingTasksistrue:- If the post already existed, sets its status to
IN_PROGRESSand clears previous errors. - Atomically enqueues a
POST_PROCESSAsyncTaskand itsAsyncTaskUnits inside the database transaction, then wakesjobRunner. - Returns
{ postId, authorId, skipUpdate: false }.
- If the post already existed, sets its status to
- If
hasPendingTasksisfalse:- Returns
{ postId, authorId, skipUpdate: true }. The caller skips task enqueueing, avoiding redundant network queries and execution cycles.
- Returns