mirror of
https://github.com/Comfy-Org/comfy-swift-sdk.git
synced 2026-11-04 23:47:26 +00:00
[PR #41] [MERGED] refactor(polling): centralize PollingFallback stream-drain into one helper #43
Labels
No labels
enhancement
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/comfy-swift-sdk#43
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/comfy-swift-sdk/pull/41
Author: @mattmillerai
Created: 7/11/2026
Status: ✅ Merged
Merged: 7/16/2026
Merged by: @mattmillerai
Base:
main← Head:matt/be-2855-pollingfallback-drain-helper📝 Commits (1)
4e1e915refactor(polling): centralize PollingFallback stream-drain into one helper📊 Changes
3 files changed (+58 additions, -68 deletions)
View changed files
📝
Sources/ComfySwiftSDK/Internal/PollingFallback.swift(+47 -0)📝
Sources/ComfySwiftSDK/Internal/ReattachCoordinator.swift(+7 -24)📝
Sources/ComfySwiftSDK/Internal/WebSocketSession.swift(+4 -44)📄 Description
ELI-5
When a job is running, the SDK normally streams progress over a WebSocket. If that socket drops, the SDK "falls back" to polling: it repeatedly asks the server for status and re-emits those updates to the caller. Two different places did this same fall-back: the WebSocket-drop handoff and the reattach path (resuming a job after the app was backgrounded).
Both places had the exact same block of code — build the poller, forward every event, and know which events mean "the job is over" so it can close the stream exactly once. Copy-pasted logic like that tends to drift: fix a bug in one and forget the other. This PR pulls that block into a single shared helper both places call, so the "which events are terminal + close-once" contract lives in one spot.
What changed
PollingFallback.drain(into:transport:jobId:startTime:clock:lastEmittedPhase:lastEmittedFraction:hasEmittedQueued:hasEmittedFinalizing:)— a static forwarder that builds aPollingFallback, drains itseventStreaminto the passed continuation, and applies the terminal-event contract (yield every event;finish()once on the first.complete/.failed/.cancelled;finish()on natural stream end; wrap any thrown error as.failed(.unknown(underlying:))then finish).WebSocketSession: the transient-error handoff now callsPollingFallback.drain(...); the privatehandOffToPollingwrapper (which held the duplicated block) is removed.ReattachCoordinator: the tail ofrunReattachnow callsPollingFallback.drain(...)instead of its own inlined copy.Why it's safe
catchwrapping); behavior is fully determined by the four resume params (lastEmittedPhase/lastEmittedFraction/hasEmittedQueued/hasEmittedFinalizing) the callers already thread.handOffToPollingwas a nonisolatedstaticon an actor;drainis likewise a nonisolatedstaticon thePollingFallbackactor, andeventStreamisnonisolated..failed(.unknown(underlying: error))yields inReattachCoordinatorare the initial job-status fetch error handlers — a single yield+finish, not the stream-drain loop — and are intentionally left untouched.Testing
swift buildclean.swift testsuite green: 226 tests, 28 suites pass. The behavior-covering suites specifically pass:PollingFallback,Reattach transient-retry,ReattachCoordinator.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.