The shape of a scheduled job
Fit when the training data changes. Predict on a schedule, against the saved context.fitted_context_id_ is a raw document id with no prefix. Store it as an opaque string beside
fitted_context_expires_at_, so a scheduler can read the deadline without a network call.
Handling expiry
A context lives 7 days from thefit that created it. Predicting against it does not extend
the clock, so anything scheduled less often than weekly will find it gone.
NotFoundError there too,
re-fit, and retry against the new context.
fitted_context_expired when yours lapsed, fitted_context_not_found
when the id was never yours. Both are NotFoundError, and re-fitting is the fix for both.
Idempotency
Passidempotency_key on every submit. A replay under the same key returns the original job
instead of queueing a second one, so a retried fit creates no second context and bills nothing.
idempotency_conflict (409) rather than a replay.
- After a re-fit the key has to change. The context is part of the fingerprint, so the old
key against the new context conflicts. Deriving the key from
fitted_context_id_handles it. - A replay is not a cached result. It returns the same job, and scored predictions are kept
1 hour — a replay after that gives you the job and
training_ref_expiredon its result.
Concurrency buys you nothing
One worker drains one queue, oldest job first. Parallel submission adds three failure modes and no throughput.- Nothing finishes sooner. Ten concurrent submits finish no earlier than ten sequential ones, because the queue is FIFO and one job runs at a time.
- Quota is reserved at submit and released at completion, so a burst can hit
quota_exceededbefore any of it has run. A job that stays queued holds its reservation until the 00:00 UTC reset. - Byte-identical payloads share one staged object. Two concurrent runs of the same deterministic batch race, and the first to finish schedules that object for deletion out from under the second.
What to retry, and what not to
Exactly four codes are retryable:rate_limited, worker_warming_up, worker_unavailable
and cache_unavailable. quota_exceeded is a 429 that is not one of them, so branch on
retryable rather than on the status code.
poll_interval, and nothing else. The loop above is yours to write.
Timeouts
Blocking calls stop waiting after 900 seconds and raiseTimeoutError. The timeout ends your
wait, not the job — it keeps running, finishes, and bills.
What to log
- The request id on every error.
err.request_idin the SDK,requestIdon the wire. A bareinvalid_requestresponse carries none, and neither does an error the SDK raises before any request. fitted_context_id_andfitted_context_expires_at_on every fit. Without the id you cannot resume, and a re-fit is the only way back.handle.job.engine_versionandhandle.job.duration_mson every terminal job. The engine version is what explains a prediction that moved.evaluation_.valueacross runs. One metric comes back per task, and its drift is the only accuracy signal you get.
evaluate() is a separate billed job that re-uploads the labeled frame, and a client resumed
from a context id cannot call it. Run it in the process that fits.
When to re-fit
Predictions assume the rows you score look like the rows you fit on. A new product line or a pricing change breaks that, and nothing warns you. Re-fitting is one call and bills your training rows once. Put it on a schedule rather than building drift detection you do not need yet.Checklist
- A stored
fitted_context_id_, withfitted_context_expires_at_beside it. NotFoundErrorcaught around both the resume and the predict, with a re-fit behind it.idempotency_keyon every submit, derived from the run day and the context id.- One worker, one queue, submissions in order.
- Retries branching on
err.retryable, with backoff you wrote. submit()plushandle.wait()wherever a timeout would otherwise lose the job.- Request id, context id, engine version and
evaluation_in your logs. - A scheduled re-fit, whether or not anything looks wrong.
Next
- The fitted context — expiry, resuming, and losing the fast path
- Errors — all 26 codes, and which four are retryable
- Limits and quotas — the daily reset and the 900-second timeout
- Usage and billing — what each job kind bills
- Troubleshooting — a symptom, its cause, and the fix