Networks fail. If a submit times out, you can't tell whether the job was queued. The fix is to create the Idempotency-Key once per job and send the same key on every retry: if the first attempt went through, the retry returns its result instead of queuing a second job. Idempotency has the rules.
Plain HTTP (Python with httpx)
import os
import random
import time
import uuid
import httpx
API = "https://api.cognichem.com/api/v1"
HEADERS = {"X-Api-Key": os.environ["COGNICHEM_API_KEY"]}
RETRY = {"upstream", "timeout", "quota"}
def submit(job, attempts=5):
key = str(uuid.uuid4()) # one key for this job, reused on every retry
for attempt in range(attempts):
try:
response = httpx.post(
f"{API}/jobs/submit",
json=job,
headers={**HEADERS, "Idempotency-Key": key},
timeout=30,
)
except httpx.TransportError:
pass # no response: safe to retry with the same key
else:
if response.status_code < 400:
return response.json()["process_id"]
problem = response.json()
if response.status_code != 409 and problem.get("retryability") not in RETRY:
raise RuntimeError(f"{problem['status']} {problem.get('detail')}")
# 409: the first attempt is still in progress; wait and retry the same key.
time.sleep(min(30, 2**attempt) + random.random())
raise RuntimeError("gave up after retries")With the Python SDK
The SDK sends a new key on every call, so for a retry loop pass your own:
import uuid
from cognichem_client import CogniChem
from cognichem_client.errors import CogniChemError
client = CogniChem.from_env()
key = str(uuid.uuid4())
for attempt in range(5):
try:
job = client.jobs.submit(
job_name="padel-batch-7",
job_type="padel-descriptor",
payload={"input_data": ["CCO"], "input_format": "smiles"},
idempotency_key=key,
)
break
except CogniChemError as error:
if error.retryability not in {"upstream", "timeout", "quota"}:
raiseDon'ts
- Don't build the key from the payload: two jobs you mean to run separately would collide, and the second would quietly return the first.
- Don't reuse a key with a changed body. That returns
409, not a second job. - Don't retry
validationorautherrors unchanged; fix the request first (Handling errors).