test(integration): poll subaccount fixture for eventual consistency#128
Conversation
POST /portfolio/subaccounts returns the new subaccount_number immediately, but GET /portfolio/subaccounts/balances lags by ~1.0-1.5s before the new account appears in the list. The ephemeral_subaccount fixture asserted the number was visible immediately after create, so it failed when the list hadn't propagated yet. Replaced the immediate return with a 10s poll loop on list_balances (0.5s interval). Soft-skips with a clear message if the new number never appears, so future demo-side issues don't masquerade as test bugs. Closes 1 of 11 integration-test failures (#124). Running tally: A (#126=4) + B (#127=1) + E (this=1) = 6 of 11. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code ReviewOverviewThis PR fixes a legitimate eventual-consistency race in the ✅ What's done well
Suggestions1. Add a log line on successful poll (minor) The fixture already logs at create time. Logging when the account becomes visible makes CI output easier to parse when investigating future failures: if any(b.subaccount_number == created for b in balances.subaccount_balances):
elapsed = time.monotonic() - (deadline - 10.0)
logger.info("Subaccount %s visible in list_balances after %.1fs", created, elapsed)
return createdNot a blocker — just adds observability in the same style as the existing 2. First poll always misses (cosmetic, not a bug) Given the ~1.0–1.5s observed lag, the first two polls (at t≈0s and t≈0.5s) will always fail before the third one (t≈1.0s) succeeds. An optional micro-optimization would be an initial Potential concernsNone that would block merging. The change is minimal, correct, and well-motivated. The VerdictLGTM. Clean, minimal fix for a legitimate flaky test root cause. The polling strategy is sound, the fallback is appropriate, and the change touches nothing beyond what's necessary. |
…ers, order_groups) (#129) * test(integration): poll for query-exchange visibility after POST Demo's query-exchange replica lags writes by ~10 seconds. Orders and order_groups created via POST aren't immediately readable via their GET-by-id endpoints — the failing tests asserted GET success immediately after CREATE and reliably hit 404 ("not_found" / service: query-exchange). Probe evidence (orders): create -> order_id X poll 1-3 (~1.5s): 404 not_found ... poll @ 10s: GET works, status=resting Same pattern for order_groups (~9.5s). - Added wait_for_resource (sync) and await_resource (async) helpers in tests/integration/helpers.py — bounded poll loop that swallows KalshiNotFoundError until timeout (default 15s, interval 0.5s) and re-raises if the resource never propagates. - Wrapped GET-after-POST sites in test_orders.py (test_order_fill_lifecycle, test_create_get_cancel sync + async) and test_order_groups.py (test_create_and_get, test_update_limit, TestOrderGroupsAsync.test_create_get_delete). - Dropped the now-redundant `await asyncio.sleep(0.5)` workaround + unused asyncio import from test_order_groups.py. Verified locally: tests/integration/test_orders.py + tests/integration/test_order_groups.py — 22/22 passed. Closes 5 of 11 integration-test failures (#124). Running tally: A (#126=4) + B (#127=1) + E (#128=1) + C (this=5) = 11/11. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * review(#129): drop dead last_error var, use PEP 695 type params Per bot review on PR #129: - Removed unused last_error assignment in wait_for_resource (ruff F841; caused CI lint failure). bare 'raise' re-raises the active exc directly, so the captured ref was dead. - Switched both helpers to PEP 695 type parameter syntax (def wait_for_resource[T](...)) to clear UP047. Drops the standalone TypeVar import. - Expanded await_resource one-line docstring with the demo-lag context so the file reads top-to-bottom. Verified: uv run ruff check . clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
`POST /portfolio/subaccounts` returns the new `subaccount_number` immediately, but `GET /portfolio/subaccounts/balances` lags by ~1.0-1.5s before the new account appears in the list. The `ephemeral_subaccount` fixture asserted visibility immediately after create, so it failed when the listing hadn't propagated yet.
Probe evidence:
```
created: 23
poll 1 (0.0s): created 23 in list? False
poll 2 (0.5s): created 23 in list? False
poll 3 (1.0s): created 23 in list? True
```
Replaced the immediate return with a 10s poll loop on `list_balances` (0.5s interval). Soft-skips with a clear message if the new number never appears within the budget.
Verification
Progress on #124
Closes 1 of 11. Running tally: A (#126=4) + B (#127=1) + E (this=1) = 6 of 11. Remaining 5 are the `not_found` cluster in test_order_groups and test_orders (likely demo limitations or test setup issue — investigating in the next PR).
Refs #124
Test plan