test(integration): add poll_until predicate; fix inventory storage-location search flake - #798
Conversation
…cation search flake
|
Code Review Issues Found
Summary |
|
Per Lenore: Rule 3 of tests/integration/TESTING.md now documents why search asserts flake (NoSQL + eventually consistent index, items index one by one), when to pass a |
Code ReviewIssues Found
Summary1 issue found. Low severity: the change is correct and works now, but the new unit test crosses the unit/integration import boundary the repo explicitly forbids. |
|
Addressed the review: |
|
Looks good - no bugs or correctness issues found. |
Polls filtered to any seeded id stop at the first partially indexed page, so assertions on a specific item or a complete set can flake. Filter each fetched page to the exact item under assertion so the default non-empty check implies the assertion; keep predicates only for true complete-set asserts (parameters id lists, inventory created_by three-way equality). Move all callers to tests.utils.wait and drop the re-export shim.
A single 5xx/429 from fetch no longer fails the poll; polling continues until the deadline and re-raises the last exception if the deadline expires on an erroring attempt. Cover the behavior plus the last-partial-result-on-timeout path in unit tests.
Whatever stops the polling must imply the assertion that follows. A timeout usually means indexing lag, but a repeat failure means the predicate or the code is wrong.
|
Review feedback applied in commits a5866e8, 7e22b9c, 968869a. A. Remaining flake sites — polls now stop only when the stop condition implies the assertion:
B. Import paths — all 18 integration callers now import C. Re-run guidance — TESTING.md now states the one rule (whatever stops the polling must imply the assertion that follows) and replaces the re-run paragraph: a timeout usually means indexing lag, but a repeat failure means the predicate or the code is wrong. Em dash removed (none remain in the file). D. Unit tests — E. Transient errors — Gates: Cake session: https://agents.ai.albertinventdev.com/sessions/910a4725-9404-4336-81dd-e30bfef0ce73 |
|
Looks good - no bugs or correctness issues found. |
prasad-albert
left a comment
There was a problem hiding this comment.
Approving. The predicate design is correct, and the "whatever stops the polling must imply the assertion that follows" rule is a great addition to TESTING.md. Two non-blocking comments:
- Narrow the exception handling in
poll_until(inline ontests/utils/wait.py). tests/unit/TESTING.md:34-35(not in this diff, so noting it here): the "never import fromtests/integration/" rule still listspoll_until, which now lives intests/utils/wait.pyand is imported by the new unit test. Suggested update:
- **Import from `tests/integration/`** (`client`, `seeded_*`, `static_*`, `seed_prefix`,
`seeding`). Shared, network-free helpers live in `tests/utils/` (e.g. `poll_until`).Fine to address in a follow-up.
| try: | ||
| result = fetch() | ||
| except Exception: | ||
| if time.monotonic() >= deadline: | ||
| raise |
There was a problem hiding this comment.
Non-blocking: except Exception catches everything fetch raises, not just transient API errors. A lambda typo (AttributeError/NameError), a ValidationError from a model change, or a NotFoundError/401 now stalls for the full 30s timeout before surfacing, across ~43 call sites. The session's urllib3 Retry already retries 500/502/503/504 (src/albert/core/session.py:78-84), so consider narrowing to server errors:
| try: | |
| result = fetch() | |
| except Exception: | |
| if time.monotonic() >= deadline: | |
| raise | |
| try: | |
| result = fetch() | |
| except AlbertServerError: | |
| if time.monotonic() >= deadline: | |
| raise |
(with from albert.exceptions import AlbertServerError). The docstring also mentions 429, which maps to AlbertClientError: either handle it deliberately or drop it from the docstring.
@claude can you address these review comments? |
|
Claude finished @prasad-albert's task in 2m 32s —— View job Review Comments Addressed
Changes made in commit
|
- `except Exception` in poll_until stalled for the full timeout on programming errors (AttributeError, ValidationError) and 4xx errors that should propagate immediately; narrow to AlbertServerError (5xx) - Remove "429" from the docstring since 429 maps to AlbertClientError and is not retried by this helper - Update unit tests: use InternalServerError instead of RuntimeError in transient-error tests; add a new test asserting non-server errors propagate immediately without polling - Update tests/unit/TESTING.md: remove poll_until from the banned tests/integration/ import list; note it lives in tests/utils/ Co-authored-by: Prasad <212564756+prasad-albert@users.noreply.github.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Looks good - no bugs or correctness issues found. |
What
Adds an optional
predicateparameter topoll_until(tests/integration/utils/wait.py) and uses it intest_inventory_search_with_name_only_storage_location_filter.Why
poll_untilstops at the first non-empty result. The inventory storage-location test asserts exact set equality ({INVA..., INVB...}), so a partially indexed search page ended polling early and the assert failed intermittently — e.g. PR #776's Integration Tests (build 8615) failed with only one of two items found, while main passed the same test a minute earlier. Nothing in #776 touches inventory.Linear: SDK-174
How
poll_until(fetch, *, predicate=...): when given, polling continues until the predicate accepts the result (default behavior unchanged: any non-empty result).tests/unit/utils/test_wait.py(default behavior, predicate waiting, timeout fallback).Testing
uv run ruff format --check/uv run ruff checkclean.uv run pytest tests/unit -q: 1123 passed, 12 xfailed (3 new).uv run pytest tests/integration --collect-only -q: 409 collected, no import errors.Cake session: https://agents.ai.albertinventdev.com/sessions/910a4725-9404-4336-81dd-e30bfef0ce73