Repository navigation
fix(apple): ignore push teardown failures after a reopen - #2055
Conversation
Reopening at once from the callback that dropped the last subscription races the closed connection's in-flight UNSUBSCRIBE. Collect onError so a teardown failure that leaks out fails this line instead of landing on stderr, where it splices into the buffered stdout the suite compares. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🟢 Tier S · Ready to merge
The Apple push SDK now tags fire-and-forget broker operations with the close generation at launch and suppresses failures from operations that cross a deliberate close, even if a later subscription reopens the connection. The Apple e2e callback teardown scenario reopens after unsubscribing the final topic and checks that no teardown error is reported. Latest changes: The newest commits add the close-generation check to
📂 Walkthrough · 2
Reviewed the commits since |
Dropping the last subscription starts a background UNSUBSCRIBE and then closes, so the UNSUBSCRIBE fails with serverClosedConnection. A subscribe() that reopens first clears 'closing', and the teardown failure then reached onError or stderr. Skip reporting when a close() has happened since the call started, as subscribe() already does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The findings that requested changes are resolved. See the summary comment for what is still open.
What
Push.inBackgroundstops reporting a fire-and-forget broker call's failure once theclose()that caused it has happened, even if a latersubscribe()has since reopened the connection and clearedclosing.Why
When the last subscription is dropped,
unsubscribestarts a background UNSUBSCRIBE and then callsclose(). The disconnect fails that in-flight UNSUBSCRIBE withMQTTError.serverClosedConnection.inBackgroundsuppressed the failure only while the globalclosingflag was set. Asubscribe()that reopens before the failure arrives resetsclosing = false. The teardown failure then surfaced as an error: toonError, or to stderr when none is registered.That stderr line is behind the intermittent
Tests / AppleSwift61failures. SwiftPM delivers the test's stdout and stderr on one stream, and stdout is block-buffered, so the lineAppwrite Push: serverClosedConnectiongets spliced into the middle of an earlier stdout line. Every expected line after it shifts. It was seen on #1955 (inside the Operator helper output) and #1817 (inside the query-transport output).The fix records
closeGenerationwhen the background call starts and skips reporting if it has changed. This is the same checksubscribe()already uses to detect an interveningclose().Tests
The "Push close from callback" e2e step now reopens from inside the callback that dropped the last subscription, which is the racing order. It also registers
onError, so a leaked teardown failure fails that one line (error: …) instead of corrupting the output stream.The test commit is pushed on its own first, so CI can show it failing without the fix. The fix follows in the next commit.
Not verified
Tests.swift, does compile withswift build --build-tests.Push.swiftused a local config with one extra key (orderedImports.shouldGroupImports), because the local swift-format is newer than 6.3. It passeslint --strict.🤖 Generated with Claude Code