Skip to content

fix: prevent duplicate platform websocket when nesting ApifyEventManager#1059

Open
vdusek wants to merge 3 commits into
masterfrom
worktree-fix-b3
Open

fix: prevent duplicate platform websocket when nesting ApifyEventManager#1059
vdusek wants to merge 3 commits into
masterfrom
worktree-fix-b3

Conversation

@vdusek

@vdusek vdusek commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

ApifyEventManager overrode Crawlee's EventManager async context manager without respecting the parent's ref counting. Crawlee ref-counts nested async with blocks, and BasicCrawler._run_crawler always re-enters the same global event manager that async with Actor: already entered. Because the override started the platform websocket machinery on every enter and tore it down on every exit, the standard async with Actor: + await crawler.run() pattern opened a second websocket connection.

On the platform this meant every platform event (MIGRATING, ABORTING, PERSIST_STATE) was delivered twice during a crawl, and on the inner exit the fields pointed at the second connection, so the first leaked and could never be cancelled. Each sequential crawler.run() added another connection; the platform caps at 10 per run and then closes with 1008 (a non-retryable code), permanently disabling platform events - so migration/abort handling silently stops for the rest of the run.

The fix mirrors the parent's ref counting: the websocket machinery is started only on the outermost enter (0 -> 1) and torn down only on the outermost exit (1 -> 0). Nested enters/exits reuse the single existing connection.

Added two regression tests: a nested enter reuses the one connection and delivers each event exactly once; a nested exit leaves the outer context's connection working while the final exit tears everything down with no leaked task.

✍️ Drafted by Claude Code

@vdusek vdusek added adhoc Ad-hoc unplanned task added during the sprint. t-tooling Issues with this label are in the ownership of the tooling team. labels Jul 21, 2026
@vdusek vdusek self-assigned this Jul 21, 2026
@github-actions github-actions Bot added this to the 145th sprint - Tooling team milestone Jul 21, 2026
@github-actions github-actions Bot added the tested Temporary label used only programatically for some analytics. label Jul 21, 2026
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.84%. Comparing base (58d6da1) to head (fbfec76).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1059      +/-   ##
==========================================
- Coverage   91.89%   91.84%   -0.05%     
==========================================
  Files          51       51              
  Lines        3232     3239       +7     
==========================================
+ Hits         2970     2975       +5     
- Misses        262      264       +2     
Flag Coverage Δ
e2e 35.25% <0.00%> (-0.08%) ⬇️
integration 56.96% <0.00%> (-0.13%) ⬇️
unit 83.23% <100.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@vdusek
vdusek requested a review from Pijukatel July 21, 2026 12:56
@vdusek
vdusek marked this pull request as ready for review July 21, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

adhoc Ad-hoc unplanned task added during the sprint. t-tooling Issues with this label are in the ownership of the tooling team. tested Temporary label used only programatically for some analytics.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants