Skip to content

Commit 38d62ad

Browse files
authored
feat(client): add per-call task deadlines (#1076)
1 parent 5e48c93 commit 38d62ad

11 files changed

Lines changed: 1119 additions & 87 deletions

File tree

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,35 @@ finally:
799799

800800
In most cases, prefer the context manager pattern.
801801

802+
### Per-call task deadlines
803+
804+
Use `TaskOptions` when a complete SDK call must fit one wall-clock budget:
805+
806+
```python
807+
from adcp import ADCPTimeoutError, TaskOptions
808+
809+
try:
810+
result = await client.create_media_buy(
811+
request,
812+
options=TaskOptions(timeout=15.0),
813+
)
814+
except ADCPTimeoutError as error:
815+
if error.recovery is not None:
816+
# Dispatch began, so the seller may have committed the mutation.
817+
# Retry the exact request with this same key; never mint a new one.
818+
retry_key = error.recovery.idempotency_key
819+
```
820+
821+
The deadline includes discovery, capability/version and signing preflight,
822+
protocol dispatch, response validation, and postflight projection. It never
823+
resets when one phase finishes. `AgentConfig.timeout` remains a separate
824+
transport timeout for connection/read-idle behavior.
825+
826+
Every single-agent task method accepts the keyword-only `options` argument.
827+
Multi-agent fan-out intentionally does not yet accept it because one timeout
828+
exception cannot safely represent several sellers' independent mutation
829+
outcomes and idempotency keys.
830+
802831
### Error Handling
803832

804833
The library provides a comprehensive exception hierarchy with helpful error messages:

src/adcp/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ def _resolve_version() -> str:
140140
"ADCPMultiAgentClient",
141141
"Checkpoint",
142142
),
143+
"adcp.task_options": (
144+
"TaskOptions",
145+
"TaskRecoveryMetadata",
146+
),
143147
"adcp.exceptions": (
144148
"AdagentsAccessBlockedError",
145149
"AdagentsNotFoundError",
@@ -843,6 +847,8 @@ def get_adcp_version() -> str:
843847
"ADCPClient",
844848
"ADCPMultiAgentClient",
845849
"Checkpoint",
850+
"TaskOptions",
851+
"TaskRecoveryMetadata",
846852
"RegistryClient",
847853
"PropertyRegistry",
848854
"RegistrySync",
@@ -1564,6 +1570,7 @@ def get_adcp_version() -> str:
15641570
encode_unreserved,
15651571
translate_universal_macros,
15661572
)
1573+
from adcp.task_options import TaskOptions, TaskRecoveryMetadata
15671574
from adcp.testing import (
15681575
CREATIVE_AGENT_CONFIG,
15691576
TEST_AGENT_A2A_CONFIG,

0 commit comments

Comments
 (0)