Skip to content

Commit f312a3d

Browse files
authored
test: stop test_actor_charge_limit from hanging on a late platform abort (#1203)
`test_actor_charge_limit` failed on master ([run](https://github.com/apify/apify-sdk-python/actions/runs/39613335682/job/119267706151)) with `TIMED-OUT` where it expected `ABORTED`. The SDK charged the expected 3 events, but the platform never aborted the run. A background daemon enforces `max_total_charge_usd`, and it usually aborts within seconds. This time it didn't, and the test Actor waited on `asyncio.Event().wait()` with no end, so the run sat until its 600 s timeout. The Actor now waits up to 60 s for the abort and then exits on its own. The test accepts `ABORTED` or `SUCCEEDED`, as `test_ppe_spider` already does, and still asserts the SDK side: `charged_event_counts == {'foobar': 3}`. When the daemon is on time, the run still ends as `ABORTED`. *✍️ Drafted by Claude Code*
1 parent c30fdcd commit f312a3d

1 file changed

Lines changed: 10 additions & 9 deletions

File tree

‎tests/e2e/test_actor_charge.py‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ async def main() -> None:
8787
)
8888
Actor.log.info('Charged', extra=asdict(charge_result))
8989

90-
# When the charge limit is reached, the platform auto-aborts this run. That abort races with the
91-
# Actor's own clean exit, making the terminal status non-deterministic (SUCCEEDED or ABORTED). Block
92-
# here so the abort always wins and the run ends deterministically as ABORTED.
90+
# When the charge limit is reached, the platform auto-aborts this run. A background daemon enforces the
91+
# limit, usually within seconds but sometimes far later. Give the abort time to arrive, but exit on our
92+
# own afterwards, so a slow daemon can't hold the run until its timeout.
9393
if charge_result.event_charge_limit_reached:
94-
await asyncio.Event().wait()
94+
await asyncio.sleep(60)
9595

9696
actor_client = await make_actor('ppe', main_func=main)
9797

@@ -156,17 +156,18 @@ async def test_actor_charge_limit(
156156
run = await run_actor(ppe_actor, max_total_charge_usd=Decimal('0.2'))
157157

158158
# The Actor charges 4 events and the budget covers 2, so the SDK charges 3 - one over the budget, which makes
159-
# the platform auto-abort the run. The Actor blocks after hitting the limit (see `ppe_actor_build`) so the abort
160-
# always wins the race against its clean exit, hence ABORTED. Refetch until the charged event counts propagate
161-
# on the platform.
159+
# the platform auto-abort the run. The Actor waits for the abort (see `ppe_actor_build`), so the run usually
160+
# ends as ABORTED, or as SUCCEEDED when the platform enforces the limit late.
161+
assert run.status in ('ABORTED', 'SUCCEEDED')
162+
163+
# Refetch until the charged event counts propagate on the platform.
162164
run = await poll_until_condition(
163165
partial(_get_run, apify_client_async, run.id),
164-
lambda r: r.status == 'ABORTED' and r.charged_event_counts == {'foobar': 3},
166+
lambda r: r.charged_event_counts == {'foobar': 3},
165167
timeout=30,
166168
poll_interval=1,
167169
)
168170

169-
assert run.status == 'ABORTED'
170171
assert run.charged_event_counts == {'foobar': 3}
171172

172173

0 commit comments

Comments
 (0)