Skip to main content
The worker owns candidate delivery and would-be-pick logging. The latest rehearsal requirements are five-minute cycles and 60 seconds from sending, including at most one retry. Only the current cycle’s on-time result may be used for that cycle’s selection. The repository includes rtb_api.client.RTBClient. It gzip-compresses cycle payloads, sends the key as the whole Authorization header and retries network errors plus 408, 429, 500, 502, 503 and 504. It preserves the request ID and body. The helper defaults to a 30-second per-operation timeout, at most one retry, and a shared 60-second total budget. It passes the remaining time to each attempt, shortens body-read socket timeouts after each chunk, checks after JSON decoding, and refuses a retry whose backoff cannot fit. An inline result received after the deadline raises RTBDeadlineExceeded; it is never returned as usable scores. GET recovery is a separate call with a separate budget. The worker must still own a strict wall-clock decision cutoff. Synchronous urllib cannot safely preempt platform DNS resolution or every internal header/TLS operation; those phases can make an exception arrive after 60 seconds even though the helper refuses late results. This helper is not an OS-level cancellation guarantee. Treat all late completion as a missed decision cycle, and reconcile later without using recovered scores for selection.
Treat this as a transport example, not a complete worker. It does not implement freshness checks, reconciliation, durable delivery or would-be-pick selection. The helper rejects unknown or invalid queue-entry clocks before sending new trial candidate data. Unknown clocks are data-quality failures to repair, not an automatic exclusion from the first-score SLA denominator. A recovered late score stays late for its original decision cycle. Keep secrets out of payload files and logs. Keep unacknowledged data until receipt has been established. Read Conventions for the proposed replay protocol and durable restart and receipt semantics.

Operator-independent pool

The DCinside worker owns this delivery policy; RTBClient is only the transport helper. Capture posts that entered and left the admin queue between five-minute polls, preserve original queue-entry clocks, and send them with source="unknown" if their source is unavailable. Keep delivering observations while they remain in the API pending pool. Under the new sender policy, saved/hidden decisions stay in client-side labels and do not trigger removals. Continue sending engagement every five-minute cycle, including after the first score, until the post is deleted or reaches the client’s 24-hour age filter. Send deleted or aged_out removals promptly. The API has no automatic 24-hour expiry; pending posts continue to be rescored until a removal is received. Hidden alone does not veto a model pick. The client skips posts currently on the real board and selects the next eligible candidate; operator intervention is through actual publication or unpublication. The API’s supplied last-20 Main/Light windows cover only those snapshots, so they cannot replace the client’s complete current-board check. Raw scores remain available even for posts excluded from a tier’s dedup ranking. For example, a post enters at 09:01+09:00, is hidden at 09:02+09:00, and is captured for the 09:05 cycle:
The first-score target remains at least 99% within two cycles after original queue entry plus 15 minutes; it is not a retention deadline. Preserve original entry clocks, client-side operator decision clocks, and the original event time for delivered removals. Late recovery can establish scoring/reconciliation facts but remains unusable for that past cycle’s selection deadline. Preserve unacknowledged requests and removals through restart. For compatibility, the API still accepts saved and hidden removals, including tier for saved. Any received removal takes effect before that cycle’s scoring. The new sender policy must stop emitting those removals; the server does not ignore them. Removed identities remain removed after restart and retransmission. Resending a previously saved/hidden-removed post does not backfill it into the new pool; any retrospective re-entry policy requires separate agreement, and no migration or reset is implied. The earlier first-score-or-25-minute hold was not activated. The proposed switch is 2026-10-15 00:00 KST, cycle 20261015T0000; it is not confirmed. Record the actual switch and cohort assignment without silently reclassifying history. Include saved/hidden posts in the first-score denominator and captured short-lived entrants in reconciliation; keep immediate early deleted/aged_out cases distinct. Track operator labels separately from API removal receipts. See cycle timing and counters. Post-decision scores use cycle-time evidence, not reconstructed decision-time evidence.

Published-window evidence

Supply published_windows.main and .light independently from the actual current published feeds. Once a post’s content has been delivered, each item needs only gall_id, post_no and placed_at; archived text and uploaded images remain available after removal. For initial published posts the API has never received, include title, body_html, images_in_post and image_positions once in those window entries, with JPEGs sent through the image upload route. Do not add already-published posts to candidates to provide this evidence. Deduplication compares scored candidates with published posts only. The API prepares the cycle’s scores and exact evidence, then waits for needed background work to settle within the remaining server budget before freezing the response. Facts completed during that wait can appear in the same cycle. Surf prioritizes the highest-scored work eligible to run; finding one usable candidate does not end the wait. Validated full-evidence unknowns remain unchecked and are reused until their evidence or model/prompt version changes. Transient failures and incomplete evidence delivery can be retried with backoff; neither unknown nor failed work is certified unique. Candidate-to-candidate checks are not performed. Recommendations and saved removals do not advance the supplied windows. Omitted context has the legacy label candidate_only and remains partial, with candidates ranked and unchecked; [] asserts a known empty feed. A published_content_missing warning means a referenced published post still needs evidence, so the affected checks remain unchecked. Use only the current cycle’s on-time returned ranking for its decision. Exclude confirmed duplicates only: do not subtract unchecked candidates or reject a ranking solely because assessment is partial, unavailable or disabled. Eligibility does not certify uniqueness and may allow actual duplicates through; bounded waiting does not extend the client’s deadline or promise whole-queue readiness. An unchanged retry resumes an unfinished prepared cycle without repeating scoring. Once a response is finalized, same-ID retries and GET return that original result; later background progress appears only in a new cycle. Response provider_calls is zero because the background worker owns model calls, including calls that overlap the HTTP wait. The client applies confirmed-duplicate-only exclusion independently to each actual rolling feed. Coordinate this client policy change with the API deployment; completed historical responses retain their original checked-only rankings. See Event deduplication.