Skip to content

fix!: reconnect to platform events websocket after connection drop - #778

Merged
vladfrangu merged 2 commits into
masterfrom
fix/reconnect-platform-events-ws
Oct 21, 2026
Merged

vladfrangu merged 2 commits into
masterfrom
fix/reconnect-platform-events-ws

Conversation

@vladfrangu

Copy link
Copy Markdown
Member

PlatformEventManager now reconnects to the platform events websocket after a drop, mirroring apify/apify-sdk-python#967. Previously a single close ended all platform events for the rest of the run, so a later migrating/aborting was missed and state was not persisted before migration.

  • Any drop is logged (warning for a lost connection, info for a clean close) and followed by a reconnect. Backoff mirrors the Python websockets schedule: random 0–5 s, then 3.1 s × 1.618 up to 90 s, reset after a connection that stayed open at least 1 s. It applies to failed attempts and to rapid open-then-close loops alike.
  • Close codes 1002, 1003, 1007, 1008 and 1010 are treated as permanent: logged as an error, no reconnect.
  • Breaking: Actor.init() now rejects when the first connection cannot be established, instead of only logging the error. Documented in the v4 upgrading guide.
  • Actor.init() registers the aborting/migrating handlers before connecting. Since init() now waits for the socket to open, the old order could miss an event sent right on connect (the existing aborting test became flaky under load).
  • close() cancels a pending backoff sleep or in-flight attempt, so shutdown never triggers a reconnect.

Tests cover fail-fast init, reconnect after a 1000 and a 1011 close, no reconnect on 1008, bounded attempts under rapid closes, recovery after the server comes back, and close() during a pending reconnect.

Closes #642

[🤖] Claude Code using Fable 5.1

`PlatformEventManager` connected to the platform events websocket once and
never reconnected after a drop, so a later `migrating` or `aborting` was
missed for the rest of the run. The connection is now re-established with
backoff (mirroring the Python SDK), except after a non-retryable close code.

BREAKING CHANGE: `Actor.init()` now rejects when the first connection to the
platform events websocket cannot be established, instead of only logging it.

Closes #642
@vladfrangu
vladfrangu requested a review from szaganek as a code owner October 14, 2026 07:09
@github-actions github-actions Bot added the t-tooling Issues with this label are in the ownership of the tooling team. label Oct 14, 2026
@apify-service-account apify-service-account added the tested Temporary label used only programatically for some analytics. label Oct 14, 2026

@barjin barjin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @vladfrangu ,

one AI-assisted issue (probably worth fixing, given how simple the fix is), but the rest seems fine 👍

Comment thread src/platform_event_manager.ts Outdated
/** Opens a new connection; resolves once it is established and rejects if it fails before that. */
async #connect(eventsWsUrl: string) {
await new Promise<void>((resolve, reject) => {
const ws = new WebSocket(eventsWsUrl);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ws apparently has no default handshake timeout. init() now waits for this, so on a silent server, Actor.init() now probably hangs forever.

Let's maybe just add this?

Suggested change
const ws = new WebSocket(eventsWsUrl);
const ws = new WebSocket(eventsWsUrl, { handshakeTimeout: 10_000 });

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, applied in a34272f with a comment explaining why. Also matches the Python websockets default open_timeout of 10 s.

[🤖] Claude Code using Fable 5.1

@vladfrangu
vladfrangu merged commit 5e3142b into master Oct 21, 2026
8 checks passed
@vladfrangu
vladfrangu deleted the fix/reconnect-platform-events-ws branch October 21, 2026 08:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

Reconnect to platform events websocket after connection drop

3 participants