feat(decisioning): time_budget deadline wrapper + incomplete projection on get_products#501
Merged
Merged
Conversation
7cca60b to
5a7b64c
Compare
…on on get_products (#495) Wraps `MediaBuyHandler.get_products` in `asyncio.wait_for` when the buyer sets `time_budget`, then projects a wire-compliant `incomplete[]` response on exhaustion. Previously the SDK ignored `time_budget` entirely. https://claude.ai/code/session_01FMKCUEQWdb8my9rXtFVQ9x
5a7b64c to
80bd2ec
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #495
Summary
Honors
GetProductsRequest.time_budgetinMediaBuyHandler.get_products. Previously the SDK ignored the field entirely; the platform ran unbounded. Now:resolve_time_budget({interval, unit})converts the wireDurationto a float seconds deadline;unit='campaign'returnsNone(no SDK-managed deadline — seller has the full campaign flight; value still reaches the adopter viaparams).get_productsshim wraps_invoke_platform_methodinasyncio.wait_for(coro, timeout=deadline)(only whendeadline is not None).asyncio.TimeoutError: logs aWARNINGwith budget info + returns{"products": [], "incomplete": [{"scope": "products", "description": "…", "estimated_wait": null}]}.IncrementalGetProductsProtocol +ProductsCheckpointdeclared and exported fromadcp.decisioning; dispatch routing ships in a follow-up (documented in AGENTS.md and the Protocol docstring).Behavioral change for existing adopters: Any adopter whose
get_productslatency exceeds a buyer'stime_budgetwill now see their coroutine cancelled and buyers will receiveincomplete[]. Previously the field was silently ignored. AWARNINGlog fires on each timeout — monitor for regressions after upgrade. The thread-pool slot leak for sync adopters (thread continues post-cancel) is documented in thetime_budget.pymodule header.Nits not fixed (noted for follow-up):
scope='products'on full timeout —pricing/forecastscope descriptions in the spec presuppose products existing, soproducts: []makes them inapplicable;proposalsscope enumeration deferred to the incremental dispatch PR.strip_credentials_from_wire_resultnot called on the SDK-generated timeout dict — the dict is known-safe (no adopter data), but worth adding defensively in the follow-up.What was tested
pytest tests/test_time_budget.py— 20 new tests, all pass: unit conversion for all 4 time units + campaign + None;project_incomplete_responseshape; 1s budget vs 10s adapter →incomplete[]; within-budget passthrough; absent budget → no deadline; campaign unit → no deadline; timeout → WARNING log; Protocol importability.pytest tests/test_decisioning_handler.py tests/test_decisioning_handler_shims.py tests/test_decisioning_dispatch.py— 109 existing tests, no regressions.pytest tests/ -x -q --ignore=tests/integration --ignore=tests/conformance) — 3210 passed, 0 failures.ruff check src/adcp/decisioning/time_budget.py src/adcp/decisioning/handler.py— clean.Pre-PR review
scope='products'is spec-correct forproducts: []case (other scopes presuppose products);campaign→no-deadline documented in module header + Protocol docstring;estimated_wait: Noneis schema-validSession: https://claude.ai/code/session_01FMKCUEQWdb8my9rXtFVQ9x
Generated by Claude Code