Skip to content

[Enhancement]Migrate sdk signaling core infra onto stream core swift#1178

Open
ipavlidakis wants to merge 29 commits into
developfrom
iliaspavlidakis/ios-1816-migrate-sdk-signaling-core-infra-onto-stream-core-swift
Open

[Enhancement]Migrate sdk signaling core infra onto stream core swift#1178
ipavlidakis wants to merge 29 commits into
developfrom
iliaspavlidakis/ios-1816-migrate-sdk-signaling-core-infra-onto-stream-core-swift

Conversation

@ipavlidakis

@ipavlidakis ipavlidakis commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🔗 Issue Links

Resolves https://linear.app/stream/issue/IOS-1816/migrate-sdk-signaling-and-core-infra-onto-stream-core-swift-websocket

🎯 Goal

StreamVideo duplicates a lot of low-level infrastructure that already lives in stream-core-swift (WebSocket client, logger, APIError, connection recovery). This PR routes both signaling WebSockets (SFU + coordinator), the logger, the API error model, and connection recovery through StreamCore instead of our own copies — removing duplication, keeping behavior consistent across Stream SDKs, and letting us track upstream fixes. It's the first, foundational step of the broader "converge StreamVideo on StreamCore" effort.

📝 Summary

  • Add stream-core-swift (from 0.8.0) as a dependency of StreamVideo, StreamVideoSwiftUI, and StreamVideoUIKit.
  • SFU signaling now runs on StreamCore.WebSocketClient via a new SFUWebSocket isolation wrapper; state exposed as a video-side SFUConnectionState.
  • Coordinator signaling now runs on StreamCore.WebSocketClient via a new CoordinatorWebSocket wrapper (auth handshake, event bridging, connectionId, state mapping).
  • Logger unified on StreamCore (video's duplicated logger deleted, re-exposed via typealiases).
  • API errors use StreamAPIError (StreamCore.APIError) across hand-written code; generated OpenAPI layer keeps its own APIError.
  • Reconnection uses StreamCore.DefaultConnectionRecoveryHandler, with the video-specific CallKit policy preserved.
  • Deleted video's now-dead WebSocket stack (client, engine, ping controller, recovery handler, providers) + their tests/mocks.

🛠 Implementation

Isolation-wrapper strategy. Importing StreamCore module-wide would collide with video's still-duplicated leaf types (ClientError, DisposableBag, Event, EventNotificationCenter, and — before this PR — the logger). To keep the blast radius small, each socket is wrapped in a single StreamCore-importing type (SFUWebSocket, CoordinatorWebSocket) that exposes a StreamCore-free, video-typed surface. Consumers (SFUAdapter, the WebRTC state machine, StreamVideo) stay StreamCore-free.

  • SFU: SFUWebSocket owns StreamCore.WebSocketClient, maps StreamCore.WebSocketConnectionState → SFUConnectionState, bridges SFU payloads (SFUEvent+StreamCore, WebRTCEventDecoder → StreamCore.AnyEventDecoder). SFUAdapter is no longer a ConnectionStateDelegate; it mirrors state via the wrapper's publisher. A SFUWebSocketProtocol + MockSFUWebSocket keep it testable.
  • Coordinator: CoordinatorWebSocket performs the WSAuthMessageRequest auth handshake on connect, decodes via video's JsonEventDecoder boxed as a StreamCore.Event (CoordinatorEvent) and forwards into video's existing EventNotificationCenter/middlewares (so event handling is unchanged), maps state back to video's WebSocketConnectionState, and exposes connectionId. StreamVideo/StreamVideoEnvironment were rewired onto it; token-refresh-on-invalid-token stays in StreamVideo.
  • Logger: deleted Publisher+Logger/Logger/LogSubsystem/LogLevel/LogConfig/destinations/formatters/Array+Logger; re-exposed StreamCore's via module-wide typealiases (StreamCoreLogging.swift). Re-added LogSubsystem.webRTCInternal + LogConfig.webRTCLogsEnabled. LogSubsystem.videoDefault works around Swift's default-argument-value rule (member must be same-module).
  • Errors: StreamAPIError = StreamCore.APIError. The transport decodes/throws it; ClientError.apiError is StreamAPIError?; token/client-error gating reads it. Only stored properties are accessed through the alias, so no StreamCore import is needed at call sites.
  • Reconnection: CoordinatorWebSocket builds StreamCore.DefaultConnectionRecoveryHandler. StreamCore's own policies are internal, so the policy set is re-implemented against StreamCore's public APIs (extracted to Coordinator/Reconnection/) to preserve internet AND wsAuto AND (background OR CallKit). CallKit's active-call check is injected as a closure (DI is ambiguous inside a StreamCore-importing file).

Follow-ups are tracked in code via a greppable [StreamCore migration] marker (reconnection policies once StreamCore makes them public; wrapper/alias/boxing removal once the event system + leaf types are unified; StreamAPIError removal once codegen emits StreamCore.APIError; restoring WebRTC log-severity sync). No public API is removed source-incompatibly; logger/error/state types are preserved by name via typealiases.

🧪 Manual Testing Notes

  • Connect/disconnect a coordinator session; verify events (call updates, ring events) still arrive and connectionId is populated.
  • Force a reconnection (toggle network / background during a call); verify the coordinator socket recovers, including backgrounded CallKit calls (CallKit reconnection policy).
  • Trigger an expired/invalid token; verify token refresh + reconnect.
  • Join a call and exercise SFU signaling (publish/subscribe, mute toggles, ICE restart) to confirm the SFU socket behaves as before.

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change follows zero ⚠️ policy (required)
  • This change should receive manual QA
  • Changelog is updated with client-facing changes
  • New code is covered by unit tests
  • Comparison screenshots added for visual changes
  • Affected documentation updated (tutorial, CMS)

Summary by CodeRabbit

  • New Features

    • Improved WebSocket connection handling, reconnection behavior, and CallKit-aware recovery.
    • Added more consistent server error reporting, including token expiration and client-error detection.
    • Unified SDK logging and WebRTC diagnostics under the shared logging system.
    • Improved SFU event and health-check processing.
  • Breaking Changes

    • Legacy logging and WebSocket APIs have been replaced by shared SDK interfaces.
    • Some custom logging destination, formatter, and publisher helpers are no longer available.

@ipavlidakis ipavlidakis self-assigned this Jul 2, 2026
@ipavlidakis
ipavlidakis requested a review from a team as a code owner July 2, 2026 14:27
@ipavlidakis ipavlidakis added the enhancement New feature or request label Jul 2, 2026
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

StreamVideo integrates StreamCore for package dependencies, errors, logging, coordinator signaling, and SFU signaling. Coordinator and SFU WebSocket flows now use StreamCore-backed wrappers, typed event conversion, published connection states, updated recovery handling, and revised test mocks.

Changes

StreamCore Migration

Layer / File(s) Summary
Dependency wiring
Package.swift, StreamVideo.xcodeproj/project.pbxproj
Adds the StreamCore package and links its product to the StreamVideo, SwiftUI, and UIKit targets.
Error and logging compatibility
Sources/StreamVideo/Errors/*, Sources/StreamVideo/Utils/Logger/*, Sources/StreamVideo/Utils/StateMachine/*, Sources/StreamVideo/Utils/Store/*
Aliases API errors and logging types to StreamCore, updates error classification and WebRTC logging, and changes default logging subsystems.
Coordinator WebSocket wrapper
Sources/StreamVideo/StreamVideo.swift, Sources/StreamVideo/StreamVideoEnvironment.swift, Sources/StreamVideo/WebSockets/Client/Coordinator/*, StreamVideoTests/WebSocketClient/*
Routes coordinator authentication, connection-state publication, event decoding, reconnection, and tests through CoordinatorWebSocket.
SFU WebSocket wrapper and adapter
Sources/StreamVideo/WebRTC/v2/SFU/*, Sources/StreamVideo/WebSockets/Client/*, Sources/StreamVideo/WebRTC/v2/StateMachine/*, StreamVideoTests/WebRTC/*
Replaces delegate and engine-based SFU wiring with typed StreamCore events, SFUWebSocket, SFUConnectionState, direct send/inject APIs, and updated mocks and assertions.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 39.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: migrating SDK signaling and core infrastructure onto StreamCore.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch iliaspavlidakis/ios-1816-migrate-sdk-signaling-core-infra-onto-stream-core-swift

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
1 Error
🚫 Please start subject with capital letter.
ae23567
1 Warning
⚠️ Big PR

Generated by 🚫 Danger

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (6)
StreamVideoTests/WebSocketClient/CoordinatorWebSocket_Tests.swift (1)

14-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rename tests to the required scenario pattern.

These test names do not follow the repository’s test_<given>_<when>_<then>_() convention.

Proposed rename
-func test_map_initializedConnectingAuthenticating() {
+func test_streamCoreStates_mapped_preservesEquivalentStates() {

-func test_map_connected_carriesConnectionId() {
+func test_connectedState_mapped_carriesConnectionId() {

-func test_map_disconnectionSources() {
+func test_disconnectionSources_mapped_preservesEquivalentSources() {

As per coding guidelines, “Name test methods with the pattern test_<given>_<when>_<then>_().”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@StreamVideoTests/WebSocketClient/CoordinatorWebSocket_Tests.swift` around
lines 14 - 49, The test methods in CoordinatorWebSocket_Tests.swift need to be
renamed to match the repository’s required test naming convention. Update the
existing tests around VideoWebSocketConnectionState mapping so each method
follows the test_<given>_<when>_<then>_ pattern, using the current scenarios in
test_map_initializedConnectingAuthenticating,
test_map_connected_carriesConnectionId, and test_map_disconnectionSources as the
basis for the new names.

Source: Coding guidelines

Sources/StreamVideo/WebSockets/Client/WebSocketInternalEvents.swift (1)

18-20: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Constant naming diverges from lowerCamelCase convention.

static let NewEventReceived uses UpperCamelCase; per guidelines, constants should use lowerCamelCase (e.g. newEventReceived).

As per coding guidelines, **/*.swift: "Use lowerCamelCase for method and variable names, and for constants".

✏️ Suggested rename (verify no external call-site breakage first)
 extension Notification.Name {
-    static let NewEventReceived = Notification.Name("io.getStream.video.core.new_event_received")
+    static let newEventReceived = Notification.Name("io.getStream.video.core.new_event_received")
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/StreamVideo/WebSockets/Client/WebSocketInternalEvents.swift` around
lines 18 - 20, Rename the Notification.Name constant in the Notification.Name
extension from NewEventReceived to lowerCamelCase to match Swift naming
conventions, and update any references to this symbol throughout the codebase;
keep the raw notification string unchanged so WebSocketInternalEvents and any
observers continue to use the same event name.

Source: Coding guidelines

Sources/StreamVideo/Utils/Logger/Logger+WebRTC.swift (1)

34-39: 🎯 Functional Correctness | 🔵 Trivial

Acknowledge the WebRTC log-severity sync regression.

The TODO correctly flags that severity is now seeded once at init from StreamCore.LogConfig.level and no longer tracks subsequent level changes, since StreamCore's LogConfig has no didSet hook. This is a real (if narrow) behavior regression versus the pre-migration implementation.

Do you want this tracked as a follow-up issue against stream-core-swift to expose a level-change hook, so syncing can be restored?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/StreamVideo/Utils/Logger/Logger`+WebRTC.swift around lines 34 - 39,
The WebRTC log-severity sync in Logger+WebRTC.swift is now only initialized from
StreamCore.LogConfig.level and no longer updates when the log level changes.
Keep the TODO in place, but add a follow-up to track restoring this behavior
once StreamCore exposes a level-change hook; reference the severity static
property and the StreamCore.LogConfig integration so it’s clear this is a
regression to be fixed in stream-core-swift.
Package.swift (1)

26-30: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider tighter pinning for the pre-1.0 stream-core-swift dependency.

.package(url:from:) resolves to .upToNextMajor(from:), so from: "0.8.0" permits any future 0.x.y release up to (excluding) 1.0.0. For a pre-1.0 SDK, minor bumps can carry breaking changes per semver convention, and other dependencies in this project (e.g. stream-video-swift-webrtc, sentry-cocoa) already use exactVersion for tighter control.

♻️ Suggested tighter pinning
-        .package(url: "https://github.com/GetStream/stream-core-swift.git", from: "0.8.0")
+        .package(url: "https://github.com/GetStream/stream-core-swift.git", exact: "0.8.0")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Package.swift` around lines 26 - 30, The `Package.swift` dependency
declaration for `stream-core-swift` is too loose for a pre-1.0 package because
`from:` allows any future `0.x.y` release. Tighten the pinning in the package
manifest by changing the `stream-core-swift` entry in the dependency list to a
fixed version (matching the project’s stricter dependency style used by
`stream-video-swift-webrtc` and `sentry-cocoa`) so updates are intentional and
controlled.
Sources/StreamVideo/WebRTC/v2/SFU/SFUWebSocket.swift (1)

94-97: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Silent message drop when engine is nil.

webSocket.engine?.send(message:) silently no-ops if engine hasn't been established yet. Combined with SFUAdapter.statusCheck() only asserting (not blocking) before calling send/sendHealthCheck, a health check, join, or leave request issued in this window fails with no log or signal back to the caller.

🛡️ Suggested fix: log when the engine is unavailable
 func send(_ message: any StreamCore.SendableEvent) {
-    webSocket.engine?.send(message: message)
+    guard let engine = webSocket.engine else {
+        log.warning("Attempted to send \(type(of: message)) with no active SFU engine.", subsystems: .sfu)
+        return
+    }
+    engine.send(message: message)
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/StreamVideo/WebRTC/v2/SFU/SFUWebSocket.swift` around lines 94 - 97,
The SFUWebSocket.send(_:), and any similar sendHealthCheck/send paths, currently
drop messages silently when webSocket.engine is nil. Update the send logic to
detect the unavailable engine case, log a clear error or warning with context,
and avoid silently no-oping; if needed, propagate a failure back through
SFUAdapter.statusCheck() callers so join/leave/health check requests get a
signal instead of disappearing.
StreamVideoTests/Mock/MockSFUStack.swift (1)

12-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Clarify that setConnectionState/receiveEvent always target the initial socket, not nextWebSocket.

webSocket is fixed at init() and never updated when nextWebSocket (i.e., box.socket) is reassigned, so setConnectionState/receiveEvent always drive the original mock socket. Current tests correctly route around this by calling .simulate/.receive directly on the new socket after a refresh, but nothing here signals that constraint to future test authors — a natural mistake (calling sfuStack.setConnectionState(...) post-refresh expecting it to hit the active socket) would silently target a stale mock.

Consider a short doc comment on setConnectionState/receiveEvent mirroring the one already on nextWebSocket.

📝 Suggested doc comments
+    /// Drives connection-state updates on the *original* socket returned by
+    /// `webSocket`. After assigning `nextWebSocket` to simulate a refresh,
+    /// interact with that new mock instance directly instead.
     func setConnectionState(to state: WebSocketConnectionState) {
         webSocket.simulate(state: .init(webSocketConnectionState: state))
     }

+    /// Delivers SFU events on the *original* socket returned by `webSocket`.
+    /// After assigning `nextWebSocket` to simulate a refresh, call `.receive`
+    /// on that new mock instance directly instead.
     func receiveEvent(_ event: WrappedEvent) {
         if case let .sfuEvent(payload) = event {
             webSocket.receive(payload)
         }
     }

Also applies to: 40-48

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@StreamVideoTests/Mock/MockSFUStack.swift` around lines 12 - 22, Add a short
doc comment on MockSFUStack’s setConnectionState and receiveEvent methods to
clarify that they always act on the original webSocket created at init, not on
nextWebSocket/box.socket after a refresh. Reference the existing nextWebSocket
property and the setConnectionState/receiveEvent helpers so future test authors
understand they must call simulate/receive on the refreshed MockSFUWebSocket
directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/StreamVideo/StreamVideo.swift`:
- Around line 565-567: The connection state updates are being handled off the
main thread in StreamVideo.connectionStateCancellable, while
handleConnectionStateChange mutates the `@Published` State.connection. Update the
connectionStatePublisher chain to hop onto DispatchQueue.main before sink so the
state change path stays on the main queue and remains safe for UI observation.

---

Nitpick comments:
In `@Package.swift`:
- Around line 26-30: The `Package.swift` dependency declaration for
`stream-core-swift` is too loose for a pre-1.0 package because `from:` allows
any future `0.x.y` release. Tighten the pinning in the package manifest by
changing the `stream-core-swift` entry in the dependency list to a fixed version
(matching the project’s stricter dependency style used by
`stream-video-swift-webrtc` and `sentry-cocoa`) so updates are intentional and
controlled.

In `@Sources/StreamVideo/Utils/Logger/Logger`+WebRTC.swift:
- Around line 34-39: The WebRTC log-severity sync in Logger+WebRTC.swift is now
only initialized from StreamCore.LogConfig.level and no longer updates when the
log level changes. Keep the TODO in place, but add a follow-up to track
restoring this behavior once StreamCore exposes a level-change hook; reference
the severity static property and the StreamCore.LogConfig integration so it’s
clear this is a regression to be fixed in stream-core-swift.

In `@Sources/StreamVideo/WebRTC/v2/SFU/SFUWebSocket.swift`:
- Around line 94-97: The SFUWebSocket.send(_:), and any similar
sendHealthCheck/send paths, currently drop messages silently when
webSocket.engine is nil. Update the send logic to detect the unavailable engine
case, log a clear error or warning with context, and avoid silently no-oping; if
needed, propagate a failure back through SFUAdapter.statusCheck() callers so
join/leave/health check requests get a signal instead of disappearing.

In `@Sources/StreamVideo/WebSockets/Client/WebSocketInternalEvents.swift`:
- Around line 18-20: Rename the Notification.Name constant in the
Notification.Name extension from NewEventReceived to lowerCamelCase to match
Swift naming conventions, and update any references to this symbol throughout
the codebase; keep the raw notification string unchanged so
WebSocketInternalEvents and any observers continue to use the same event name.

In `@StreamVideoTests/Mock/MockSFUStack.swift`:
- Around line 12-22: Add a short doc comment on MockSFUStack’s
setConnectionState and receiveEvent methods to clarify that they always act on
the original webSocket created at init, not on nextWebSocket/box.socket after a
refresh. Reference the existing nextWebSocket property and the
setConnectionState/receiveEvent helpers so future test authors understand they
must call simulate/receive on the refreshed MockSFUWebSocket directly.

In `@StreamVideoTests/WebSocketClient/CoordinatorWebSocket_Tests.swift`:
- Around line 14-49: The test methods in CoordinatorWebSocket_Tests.swift need
to be renamed to match the repository’s required test naming convention. Update
the existing tests around VideoWebSocketConnectionState mapping so each method
follows the test_<given>_<when>_<then>_ pattern, using the current scenarios in
test_map_initializedConnectingAuthenticating,
test_map_connected_carriesConnectionId, and test_map_disconnectionSources as the
basis for the new names.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 40f3075c-e545-460e-8db3-5c80758d8e57

📥 Commits

Reviewing files that changed from the base of the PR and between c4fdf80 and 52a3f7c.

📒 Files selected for processing (77)
  • Package.swift
  • Sources/StreamVideo/Errors/Errors.swift
  • Sources/StreamVideo/Errors/StreamAPIError.swift
  • Sources/StreamVideo/OpenApi/URLSessionTransport.swift
  • Sources/StreamVideo/StreamVideo.swift
  • Sources/StreamVideo/StreamVideoEnvironment.swift
  • Sources/StreamVideo/Utils/ClientEventReporting/ClientEventFailure.swift
  • Sources/StreamVideo/Utils/Extensions/Concurrency/Task+DisposableBag.swift
  • Sources/StreamVideo/Utils/Logger/Array+Logger.swift
  • Sources/StreamVideo/Utils/Logger/Data+DebugPrettyPrintedJSON.swift
  • Sources/StreamVideo/Utils/Logger/Destination/BaseLogDestination.swift
  • Sources/StreamVideo/Utils/Logger/Destination/ConsoleLogDestination.swift
  • Sources/StreamVideo/Utils/Logger/Destination/LogDestination.swift
  • Sources/StreamVideo/Utils/Logger/Formatter/LogFormatter.swift
  • Sources/StreamVideo/Utils/Logger/Formatter/PrefixLogFormatter.swift
  • Sources/StreamVideo/Utils/Logger/Logger+WebRTC.swift
  • Sources/StreamVideo/Utils/Logger/Logger.swift
  • Sources/StreamVideo/Utils/Logger/Publisher+Logger.swift
  • Sources/StreamVideo/Utils/Logger/StreamCoreLogging.swift
  • Sources/StreamVideo/Utils/StateMachine/StreamStateMachine.swift
  • Sources/StreamVideo/Utils/Store/StoreLogger.swift
  • Sources/StreamVideo/WebRTC/WebRTCEventDecoder.swift
  • Sources/StreamVideo/WebRTC/v2/SFU/Protocols/WebSocketClientProviding.swift
  • Sources/StreamVideo/WebRTC/v2/SFU/SFUAdapter.swift
  • Sources/StreamVideo/WebRTC/v2/SFU/SFUConnectionState.swift
  • Sources/StreamVideo/WebRTC/v2/SFU/SFUEvent+StreamCore.swift
  • Sources/StreamVideo/WebRTC/v2/SFU/SFUWebSocket.swift
  • Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Disconnected.swift
  • Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+FastReconnecting.swift
  • Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Joined.swift
  • Sources/StreamVideo/WebRTC/v2/StateMachine/Stages/WebRTCCoordinator+Stage.swift
  • Sources/StreamVideo/WebRTC/v2/WebRTCAuthenticator.swift
  • Sources/StreamVideo/WebSockets/Client/ConnectionRecoveryHandler.swift
  • Sources/StreamVideo/WebSockets/Client/ConnectionStatus.swift
  • Sources/StreamVideo/WebSockets/Client/Coordinator/CoordinatorEventDecoder.swift
  • Sources/StreamVideo/WebSockets/Client/Coordinator/CoordinatorWebSocket.swift
  • Sources/StreamVideo/WebSockets/Client/Coordinator/CoordinatorWebSocketTypes.swift
  • Sources/StreamVideo/WebSockets/Client/Coordinator/Reconnection/BackgroundStateReconnectionPolicy.swift
  • Sources/StreamVideo/WebSockets/Client/Coordinator/Reconnection/CallKitReconnectionPolicy.swift
  • Sources/StreamVideo/WebSockets/Client/Coordinator/Reconnection/CompositeReconnectionPolicy.swift
  • Sources/StreamVideo/WebSockets/Client/Coordinator/Reconnection/InternetAvailabilityReconnectionPolicy.swift
  • Sources/StreamVideo/WebSockets/Client/Coordinator/Reconnection/WebSocketAutomaticReconnectionPolicy.swift
  • Sources/StreamVideo/WebSockets/Client/HealthCheckInfo.swift
  • Sources/StreamVideo/WebSockets/Client/URLSessionWebSocketEngine.swift
  • Sources/StreamVideo/WebSockets/Client/WebSocketClient.swift
  • Sources/StreamVideo/WebSockets/Client/WebSocketEngine.swift
  • Sources/StreamVideo/WebSockets/Client/WebSocketEngineError.swift
  • Sources/StreamVideo/WebSockets/Client/WebSocketInternalEvents.swift
  • Sources/StreamVideo/WebSockets/Client/WebSocketPingController.swift
  • StreamVideo.xcodeproj/project.pbxproj
  • StreamVideoTests/Call/Call_JoinRecovery_Tests.swift
  • StreamVideoTests/IntegrationTests/Call_IntegrationTests.swift
  • StreamVideoTests/Mock/MockCoordinatorWebSocket.swift
  • StreamVideoTests/Mock/MockSFUStack.swift
  • StreamVideoTests/Mock/MockWebSocketClientFactory.swift
  • StreamVideoTests/Mock/WebSocketClientEnvironment_Mock.swift
  • StreamVideoTests/Mock/WebSocketEngine_Mock.swift
  • StreamVideoTests/Mock/WebSocketPingController_Mock.swift
  • StreamVideoTests/TestUtils/WebSocketPingController_Delegate.swift
  • StreamVideoTests/Utils/ClientEventReporting/ClientEventDelivery_Tests.swift
  • StreamVideoTests/Utils/ClientEventReporting/ClientEventFailure_Tests.swift
  • StreamVideoTests/Utils/ClientEventReporting/ClientEventReporter_Tests.swift
  • StreamVideoTests/WebRTC/Retries_Tests.swift
  • StreamVideoTests/WebRTC/SFU/Mocks/MockSFUWebSocket.swift
  • StreamVideoTests/WebRTC/SFU/Mocks/MockWebSocketClient.swift
  • StreamVideoTests/WebRTC/SFU/Mocks/MockWebSocketEngine.swift
  • StreamVideoTests/WebRTC/SFU/SFUAdapter_Tests.swift
  • StreamVideoTests/WebRTC/SFU/SFUEventAdapter_Tests.swift
  • StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_DisconnectedStageTests.swift
  • StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_FastReconnectingStageTests.swift
  • StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_JoinedStageTests.swift
  • StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_JoiningStageTests.swift
  • StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_LeavingStageTests.swift
  • StreamVideoTests/WebRTC/v2/StateMachine/Stages/WebRTCCoordinatorStateMachine_RejoiningStageTests.swift
  • StreamVideoTests/WebSocketClient/CoordinatorWebSocket_Tests.swift
  • StreamVideoTests/WebSocketClient/WebSocketClient_Tests.swift
  • StreamVideoTests/WebSocketClient/WebSocketPingController_Tests.swift
💤 Files with no reviewable changes (23)
  • Sources/StreamVideo/WebSockets/Client/WebSocketClient.swift
  • StreamVideoTests/Mock/MockWebSocketClientFactory.swift
  • StreamVideoTests/WebSocketClient/WebSocketPingController_Tests.swift
  • Sources/StreamVideo/Utils/Logger/Formatter/PrefixLogFormatter.swift
  • StreamVideoTests/TestUtils/WebSocketPingController_Delegate.swift
  • Sources/StreamVideo/Utils/Logger/Publisher+Logger.swift
  • Sources/StreamVideo/WebSockets/Client/WebSocketEngine.swift
  • StreamVideoTests/Mock/WebSocketPingController_Mock.swift
  • Sources/StreamVideo/WebSockets/Client/ConnectionRecoveryHandler.swift
  • Sources/StreamVideo/Utils/Logger/Destination/ConsoleLogDestination.swift
  • StreamVideoTests/Mock/WebSocketClientEnvironment_Mock.swift
  • Sources/StreamVideo/Utils/Logger/Formatter/LogFormatter.swift
  • Sources/StreamVideo/Utils/Logger/Destination/LogDestination.swift
  • Sources/StreamVideo/WebSockets/Client/URLSessionWebSocketEngine.swift
  • StreamVideoTests/WebRTC/SFU/Mocks/MockWebSocketClient.swift
  • StreamVideoTests/Mock/WebSocketEngine_Mock.swift
  • Sources/StreamVideo/Utils/Logger/Array+Logger.swift
  • Sources/StreamVideo/Utils/Logger/Destination/BaseLogDestination.swift
  • Sources/StreamVideo/WebRTC/v2/SFU/Protocols/WebSocketClientProviding.swift
  • StreamVideoTests/WebRTC/SFU/Mocks/MockWebSocketEngine.swift
  • StreamVideoTests/WebSocketClient/WebSocketClient_Tests.swift
  • Sources/StreamVideo/WebSockets/Client/WebSocketPingController.swift
  • Sources/StreamVideo/Utils/Logger/Logger.swift

Comment thread Sources/StreamVideo/StreamVideo.swift
@ipavlidakis
ipavlidakis force-pushed the iliaspavlidakis/ios-1816-migrate-sdk-signaling-core-infra-onto-stream-core-swift branch from 52a3f7c to 820fd02 Compare July 3, 2026 08:31
@ipavlidakis ipavlidakis changed the title Iliaspavlidakis/ios 1816 migrate sdk signaling core infra onto stream core swift [Enhancement]Migrate sdk signaling core infra onto stream core swift Jul 3, 2026

@martinmitrevski martinmitrevski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

partial review, will proceed at some point again

Comment thread Sources/StreamVideo/Utils/Logger/Data+DebugPrettyPrintedJSON.swift Outdated
Comment thread Sources/StreamVideo/Utils/Extensions/Concurrency/Task+DisposableBag.swift Outdated
/// `StreamAPIError` and the generated `APIError`) goes away once the OpenAPI
/// generator is changed to emit `APIError` as `StreamCore.APIError`. Then the
/// whole app uses one API error type and this file can be deleted.
public typealias StreamAPIError = StreamCore.APIError

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can't we use the APIError directly?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There are currently two nominally different APIError types: the generated StreamVideo.APIError and StreamCore.APIError. Using bare APIError resolves to the generated model, not StreamCore’s type. StreamAPIError therefore disambiguates Core errors without requiring import StreamCore in every consumer, which would also introduce symbol collisions. ClientError.apiError remains the generated type for source compatibility, with Core errors converted at the boundary. The alias can be removed once the generated model migrates to StreamCore (which i'm not even sure if it's possible to happen as it will require backend to align the apiErrors between chat and video and potentially feeds).

// them under their historical StreamVideo names so existing call sites keep
// working module-wide without importing StreamCore in every file.

public typealias LogLevel = StreamCore.LogLevel

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can't we solve this with @_exported import StreamCore?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

An exported import would expose all of StreamCore downstream and introduce collisions with Video’s existing types. The focused aliases preserve compatibility without broadening the public module surface, so I’ve kept the current approach.

@martinmitrevski martinmitrevski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

looks good so far. There's still some potential to reduce the SDK size further.

/// therefore cannot import StreamCore). `SFUWebSocket` maps
/// `StreamCore.WebSocketConnectionState` into this type at the boundary.
///
/// - TODO: [StreamCore migration] This boundary enum exists so the WebRTC state

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't really understand this reasoning, wdym by unifying leaf types?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Those are are the leaf types #1195 (basically types that are primitive but they are being used as they are without extensions)

/// the WebRTC state machine never import StreamCore.
///
/// - TODO: [StreamCore migration] This isolation wrapper exists because video
/// still owns duplicated leaf types (`log`, `ClientError`, `DisposableBag`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

are there any blockers for unifying them or is it just still not done?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

There is no fundamental blocker; it is intentionally deferred to keep this migration focused. The wrapper still normalizes StreamCore connection states, errors, and events into the types consumed by SFUAdapter, and provides its test-mocking seam. Removing it requires migrating SFUAdapter, the WebRTC state machine, and their mocks to consume StreamCore types directly. I’ve updated the documentation to make this remaining work explicit.

@ipavlidakis
ipavlidakis force-pushed the iliaspavlidakis/ios-1816-migrate-sdk-signaling-core-infra-onto-stream-core-swift branch 2 times, most recently from 83b030c to 366624e Compare July 13, 2026 08:41
@github-actions

Copy link
Copy Markdown

Public Interface

+ extension StreamCore.LogConfig  
+ 
+   public static var webRTCLogsEnabled: Bool

+ extension LogSubsystem  
+ 
+   public static let videoDefault

+ extension Stream_Video_Sfu_Event_SfuEvent.OneOf_EventPayload: StreamCore.Event  
+ 
+   public func healthcheck()-> StreamCore.HealthCheckInfo?
+   public func error()-> Error?

- public class PrefixLogFormatter: LogFormatter  
- 
-   public init(prefixes: [LogLevel: String])
-   
- 
-   public func format(logDetails: LogDetails,message: String)-> String

- public struct LogDetails: Sendable  
- 
-   public let loggerIdentifier: String
-   public let subsystem: LogSubsystem
-   public let level: LogLevel
-   public let date: Date
-   public let message: String
-   public let threadName: String
-   public let functionName: StaticString
-   public let fileName: StaticString
-   public let lineNumber: UInt
-   public let error: Error?

- public protocol LogDestination: Sendable

- public extension LogDestination

- public struct Log: Publisher  
- 
-   public func receive(subscriber: S)

- public final class ConsoleLogDestination: BaseLogDestination, @unchecked Sendable  
- 
-   override public func write(message: String)

- public enum LogConfig  
- 
-   public nonisolated static var identifier
-   public nonisolated static var level: LogLevel
-   public nonisolated static var dateFormatter: DateFormatter
-   public nonisolated static var formatters
-   public nonisolated static var showDate
-   public nonisolated static var showLevel
-   public nonisolated static var showIdentifier
-   public nonisolated static var showThreadName
-   public nonisolated static var showFileName
-   public nonisolated static var showLineNumber
-   public nonisolated static var showFunctionName
-   public nonisolated static var subsystems: LogSubsystem
-   public nonisolated static var destinationTypes: [LogDestination.Type]
-   public static var destinations: [LogDestination]
-   public static var logger: Logger
-   public static var webRTCLogsEnabled: Bool

- public class Logger: @unchecked Sendable  
- 
-   public let identifier: String
-   public var destinations: [LogDestination]
-   
- 
-   public init(identifier: String = "",destinations: [LogDestination] = [])
-   
- 
-   public func callAsFunction(_ level: LogLevel,functionName: StaticString = #function,fileName: StaticString = #fileID,lineNumber: UInt = #line,message: @autoclosure () -> Any,subsystems: LogSubsystem = .other,error: Error?)
-   public func log(_ level: LogLevel,functionName: StaticString = #function,fileName: StaticString = #fileID,lineNumber: UInt = #line,message: @autoclosure () -> Any,subsystems: LogSubsystem = .other,error: Error?)
-   public func info(_ message: @autoclosure () -> Any,subsystems: LogSubsystem = .other,functionName: StaticString = #function,fileName: StaticString = #fileID,lineNumber: UInt = #line)
-   public func debug(_ message: @autoclosure () -> Any,subsystems: LogSubsystem = .other,functionName: StaticString = #function,fileName: StaticString = #fileID,lineNumber: UInt = #line)
-   public func warning(_ message: @autoclosure () -> Any,subsystems: LogSubsystem = .other,functionName: StaticString = #function,fileName: StaticString = #fileID,lineNumber: UInt = #line)
-   public func error(_ message: @autoclosure () -> Any,subsystems: LogSubsystem = .other,error: Error? = nil,functionName: StaticString = #function,fileName: StaticString = #fileID,lineNumber: UInt = #line)
-   public func assert(_ condition: @autoclosure () -> Bool,_ message: @autoclosure () -> Any,subsystems: LogSubsystem = .other,functionName: StaticString = #function,fileName: StaticString = #fileID,lineNumber: UInt = #line)
-   public func assertionFailure(_ message: @autoclosure () -> Any,subsystems: LogSubsystem = .other,functionName: StaticString = #function,fileName: StaticString = #fileID,lineNumber: UInt = #line)

- extension Array  
- 
-   public func log(_ level: LogLevel,subsystems: LogSubsystem = .other,functionName: StaticString = #function,fileName: StaticString = #fileID,lineNumber: UInt = #line,messageBuilder: ((Self) -> String)? = nil)-> Self

- open class BaseLogDestination: LogDestination, @unchecked Sendable  
- 
-   open var identifier: String
-   open var level: LogLevel
-   open var subsystems: LogSubsystem
-   open var dateFormatter: DateFormatter
-   open var formatters: [LogFormatter]
-   open var showDate: Bool
-   open var showLevel: Bool
-   open var showIdentifier: Bool
-   open var showThreadName: Bool
-   open var showFileName: Bool
-   open var showLineNumber: Bool
-   open var showFunctionName: Bool
-   
- 
-   public required init(identifier: String,level: LogLevel,subsystems: LogSubsystem,showDate: Bool,dateFormatter: DateFormatter,formatters: [LogFormatter],showLevel: Bool,showIdentifier: Bool,showThreadName: Bool,showFileName: Bool,showLineNumber: Bool,showFunctionName: Bool)
-   
- 
-   open func isEnabled(level: LogLevel)-> Bool
-   open func isEnabled(level: LogLevel,subsystems: LogSubsystem)-> Bool
-   open func process(logDetails: LogDetails)
-   open func applyFormatters(logDetails: LogDetails,message: String)-> String
-   open func write(message: String)

- public struct LogSubsystem: OptionSet, CustomStringConvertible, Sendable  
- 
-   public let rawValue: Int
-   public static let allCases: [LogSubsystem]
-   public static let all: LogSubsystem
-   public static let other
-   public static let database
-   public static let httpRequests
-   public static let webSocket
-   public static let offlineSupport
-   public static let webRTC
-   public static let peerConnectionPublisher
-   public static let peerConnectionSubscriber
-   public static let sfu
-   public static let iceAdapter
-   public static let mediaAdapter
-   public static let thermalState
-   public static let audioSession
-   public static let videoCapturer
-   public static let pictureInPicture
-   public static let callKit
-   public static let webRTCInternal
-   public static let audioRecording
-   public var description: String
-   
- 
-   public init(rawValue: Int)

- public enum LogLevel: Int, Sendable  
- 
-   case debug = 0
-   case info
-   case warning
-   case error

- public class WebSocket: ClientError, @unchecked Sendable

- public protocol LogFormatter

 extension Task  
-   @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async -> Success)
+   @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .videoDefault,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async -> Success)
-   @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .other,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async throws -> Success)
+   @discardableResult public init(disposableBag: DisposableBag,identifier: String = UUIDProviderKey.currentValue.get().uuidString,priority: TaskPriority? = nil,subsystem: LogSubsystem = .videoDefault,file: StaticString = #file,function: StaticString = #function,line: UInt = #line,@_inheritActorContext block: @Sendable @escaping () async throws -> Success)

 public final class StreamStateMachine  
-   public init(initialStage: StageType,logSubsystem: LogSubsystem = .other)
+   public init(initialStage: StageType,logSubsystem: LogSubsystem = .videoDefault)

Ilias Pavlidakis and others added 14 commits July 17, 2026 12:08
Add the StreamCore package dependency (>= 0.8.0) to the StreamVideo target via
SPM and the Xcode project. No imports yet — this only establishes linkage for
the upcoming isolated WebSocket wrappers. Behaviour and public API unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
… (WebSocket, logger, error model, reconnection)

# Conflicts:
#	Sources/StreamVideo/WebSockets/Client/WebSocketClient.swift
#	StreamVideoTests/Mock/WebSocketEngine_Mock.swift
#	StreamVideoTests/WebSocketClient/WebSocketClient_Tests.swift
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@ipavlidakis
ipavlidakis force-pushed the iliaspavlidakis/ios-1816-migrate-sdk-signaling-core-infra-onto-stream-core-swift branch from ca91f80 to 1a44ddf Compare July 17, 2026 09:09

@martinmitrevski martinmitrevski left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good, let's test it a bit before merging. Left few comments as well.

Comment thread Sources/StreamVideo/Errors/StreamAPIError.swift Outdated

public extension RawJSON {
/// Extracts the wrapped value as the specified type, if possible.
func value<T>() -> T? {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

shouldn't this go into StreamCore?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

If chat or feeds not using it, there is no reason to move it down to Core, right?

log.error("Error refreshing token, will disconnect ws connection", error: error)
}
} else {
connectionRecoveryHandler?.webSocketClient(client, didUpdateConnectionState: state)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we don't need this any longer?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The connectionRecoveryHandler is now part of the CoordinatorWebsocket, which is now the delegate to the handler https://github.com/GetStream/stream-video-swift/pull/1178/changes#diff-66385429e716ff2693e908df6930e45f6baf756f7a9dc83caac3cc07065b1bd5R148

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Just to be sure i added also a test to ensure connection recovery in CoordinatorWebSocket_Tests

//

import Combine
import enum StreamCore.RawJSON

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

do we need to be this specific? Why not the whole core?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Because we aren't consuming everything from StreamCore directly yet (mainly now the problem is the APIError) we rely on typealiases. That means that in files that both StreamCore and StreamVideo types collide, they create ambiguation causing compilation errors. The specific import is to avoid this problem. Once the APIError migration is in we can go through those specific imports and check if we can remove them but for now that should be fine.

@ipavlidakis
ipavlidakis force-pushed the iliaspavlidakis/ios-1816-migrate-sdk-signaling-core-infra-onto-stream-core-swift branch from b7c140f to 5ad7433 Compare July 23, 2026 22:28
) {
if case let .disconnected(source) = state,
let serverError = source.serverError,
serverError.isInvalidTokenError || serverError.isTokenExpiredError {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

If the token is expired, it doesn't forward the event to the recoveryHandler so no reconnection is being triggered.

coordinatorHealthCheck: .init(
cid: nil,
connectionId: connectedEvent.connectionId,
createdAt: connectedEvent.createdAt

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The StreamCore.HealthcheckInfo has no createdAt field

)
if let connectURL = try? URL(string: Self.endpointConfig.wsEndpoint)?.appendingQueryItems(queryParams) {
webSocketClient = makeWebSocketClient(url: connectURL, apiKey: apiKey)
webSocketClient = makeWebSocketClient(url: connectURL)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We don't need to pass in the apiKey any more as it's embedded in the connectURL

log.error("Error refreshing token, will disconnect ws connection", error: error)
}
if let serverError = source.serverError,
serverError.isInvalidTokenError || serverError.isTokenExpiredError {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the supplementary part for the token refresh and the WebsocketReconnectionPolicy. During a websocket disconnection StreamVideo and the CoordinatorWebsocket are being informed. If the disconnection was due to tokenExpired, then the CoordinatorWebsocket does nothing while StreamVideo kicks in a token refresh.

@Stream-SDK-Bot

Copy link
Copy Markdown
Collaborator

SDK Size

title develop branch diff status
StreamVideo 10.56 MB 9.38 MB -1209 KB 🚀
StreamVideoSwiftUI 2.47 MB 2.47 MB +1 KB 🟢
StreamVideoUIKit 2.61 MB 2.61 MB +1 KB 🟢
StreamWebRTC 11.87 MB 11.87 MB 0 KB 🟢

@Stream-SDK-Bot

Copy link
Copy Markdown
Collaborator

StreamVideo XCSize

Object Diff (bytes)
WebRTCStateAdapter.o -83020
ApplicationLifecycleVideoMuteAdapter.o -68547
CallKitAlwaysAvailabilityPolicy.o -52714
APIHelper.o -48738
Errors.o -48363
Show 482 more objects
Object Diff (bytes)
SFUAdapter.o -45963
Protobuf+SelectiveEncodable.o -44654
StreamVideo.o -43441
CallKitService.o -40355
Signposting.o +35848
RTCPeerConnectionCoordinator.o -33481
WebSocketClient.o -32143
URLSessionWebSocketEngine.o -32056
ConnectionRecoveryHandler.o -31550
Logger.o -24953
Call.o -24254
StreamCallAudioRecorder.o -20745
User.o -19255
CallSettings.o -18632
LocalVideoMediaAdapter.o -15449
ReflectiveStringConvertible.o -14567
SignalServerEvent.o -13526
RawJSON.o -13385
InternetConnection.o -12899
Device.o -12810
ScreenShareCaptureHandler.o -12564
APIError.o -12287
VideoInternetConnection.o +12052
CreateDeviceRequest.o -11990
WebSocketPingController.o -11954
WebRTCPermissionsAdapter.o +11332
CallsController.o -11180
WebRTCCoordinator+Joined.o -10144
LocalScreenShareMediaAdapter.o -10103
ConnectUserDetailsRequest.o -9775
Models.o -9466
WebRTCCoordinator.o +9415
BaseLogDestination.o -9042
ICEAdapter.o -8180
WSAuthMessageRequest.o -8153
Publisher+Logger.o -8053
ListDevicesResponse.o -7940
NoiseCancellationFilter.o -7590
SFUEventAdapter.o -7414
WebRTCAuthenticator.o +7376
StreamVideoEnvironment.o -7137
AudioBufferRenderer.o -7100
LocalAudioMediaAdapter.o -7005
CameraCaptureHandler.o -6952
HTTPClient.o -6868
RTCAudioStore+AudioDeviceModuleMiddleware.o -6758
CallKitPushNotificationAdapter.o -6292
StreamCallAudioRecorder+AVAudioRecorderMiddleware.o -6060
StreamJsonDecoder.o -5532
Token.o -5495
ModelResponse.o -5282
EventNotificationCenter.o -5265
BackgroundTaskScheduler.o -5100
TimerPublisher.o -5089
ProximityManager.o -4980
DisposableBag.o -4967
WebRTCStatsReporter.o -4890
PeerConnectionFactory.o -4887
RepeatingTimer.o -4687
BroadcastCaptureHandler.o -4616
LogDestination.o -4597
ConnectionStatus.o -4596
StreamVideoCapturer.o -4576
URLSessionTransport.o -4494
OpenISO8601DateFormatter.o -4372
Event.o -4184
events.pb.o +4008
EventBatcher.o -4000
PermissionsStore.o -3514
CameraFocusHandler.o -3508
RawJSON+StreamCore.o +3432
VideoProximityPolicy.o -3348
WebRTCStatsAdapter.o -3320
OutgoingRingingController.o -3286
CallAudioSession.o -3253
CodableHelper.o -3089
WebRTCCoordinator+Disconnected.o -3078
CameraSystemPressureHandler.o -3032
WebRTCTracesAdapter.o -3011
UserRequest.o +2978
DefaultTimer.o -2949
WebSocketJoinTelemetryReporter.o -2940
AudioEngineLevelNodeAdapter.o -2903
CallKitAdapter.o -2892
CameraInterruptionsHandler.o -2848
SFUWebSocket.o +2812
WebRTCStatsCollector.o -2780
VideoCaptureSession.o -2748
ScreenShareSession.o -2740
OperationQueue+TaskOperations.o -2688
StreamCore_-14BA7DE23376E301_PackageProduct +2684
BroadcastBufferReader.o -2670
InjectedValues.o -2668
CallCache.o -2647
WebRTCCoordinator+Connecting.o -2548
SpeakerProximityPolicy.o -2520
Publisher+TaskSink.o -2496
VideoEvent+ReflectiveStringConvertible.o +2432
LastParticipantAutoLeavePolicy.o -2390
Call+Error.o -2368
WebRTCCoordinator+Error.o -2280
APIKey.o -2266
WebRTCCoordinator+FastReconnecting.o -2256
WebRTCCoordinator+Joining.o -2063
WebRTCCoordinator+Stage.o -2016
StreamAppStateAdapter.o -1986
StreamStateMachine.o -1940
JoinedStateTelemetryReporter.o -1940
ThermalStateObserver.o -1936
IndividualRecordingSettingsResponse.o -1928
CoordinatorWebSocket.o +1887
AudioFilter.o -1806
WebRTCCoordinator+Migrated.o -1732
ClientEventDelivery.o -1712
WebRTCCoordinator+PeerConnectionPreparing.o +1704
RTCRtpTransceiverInit+Convenience.o -1660
WebRTCMigrationStatusObserver.o -1608
StreamCallAudioRecorder+Logger.o -1598
HTTPUtils.o -1568
StereoEnableVisitor.o +1540
CameraManager.o -1484
StreamVideoCaptureHandler.o -1448
RejectionReasonProvider.o -1440
PermissionStore+PushNotificationsMiddleware.o -1420
Task+Timeout.o -1384
VideoMediaAdapter.o -1360
ScreenShareMediaAdapter.o -1360
StreamRTCPeerConnection.o -1354
JsonEventDecoder.o -1325
Call+LeavingStage.o -1319
SimulatorScreenCapturer.o -1273
Encodable+Retroactive.o -1272
AVAudioConverter+Convert.o -1224
StoreLogger.o -1196
WebSocketEngine.o -1194
RetryStrategy.o -1188
CallState.o -1176
Call+Stage.o -1158
ConsoleLogDestination.o -1093
RTCAudioStore+AVAudioSessionReducer.o -1088
Moderation+VideoAdapter.o -1084
RecursiveQueue.o -1065
UnfairQueue.o -1026
signal.pb.o +1020
SwiftProtobuf.o +1000
Logger+WebRTC.o -963
PublishOptions.o -960
AudioDeviceModule.o -957
GeofenceSettings.o +948
JSONDataEncoding.o -908
WebRTCTrackStorage.o +884
BroadcastBufferUploader.o -872
MediaAdapter.o +868
PrefixLogFormatter.o -854
Atomic.o -850
Task+DisposableBag.o -696
WebSocketClientProviding.o -660
CoordinatorModels.o -644
CallState+Machine.o +629
Foundation.tbd -620
Call+JoiningStage.o -617
EventMiddleware.o -614
SFUEvent+StreamCore.o +588
Call+JoinedStage.o -588
AudioSettings.o +560
Extensions.o -548
CallParticipant.o -526
models.pb.o +508
RTCTemporaryPeerConnection.o +506
VideoEvent.o -470
WebRTCCoordinator+Rejoining.o -468
CallStatsReport.o -464
AudioMediaAdapter.o -464
AudioCustomProcessingModule.o -460
AVAudioSessionRouteDescription+Convenience.o -435
CallKitReconnectionPolicy.o +423
Call+AcceptingStage.o -416
AudioProcessingStore+AudioFilterMiddleware.o -408
StreamVideoProcessPipeline.o -400
BroadcastSampleHandler.o -394
ConsumableBucket.o -388
signal.twirp.o +375
ClientCapability.o +368
WebRTCCoordinator+Leaving.o -364
WebRTCCoordinator+Blocked.o -360
WebRTCCoordinator+StateMachine.o +360
WebRTCCoordinator+CleanUp.o -356
WebRTCCoordinator+Migrating.o -348
SpeakerManager.o -320
CallEvent.o +316
ClientEvent.o +299
StreamDeviceOrientationAdapter.o -288
RTCAudioStore.o +268
RTCMediaStream+CustomStringConvertible.o -260
BatteryStore.o -250
EdgeResponse.o +248
WebRTCEventDecoder.o +246
LayoutSettings.o +224
CallSessionParticipantCountsUpdatedEvent.o +220
GetOrCreateCallResponse.o +216
CallRequest.o +216
CallSessionResponse.o +216
ICEConnectionStateAdapter.o +212
BatteryStore+ObservationMiddleware.o -208
ClosedCaptionsAdapter.o +208
RTCAudioStore+StereoPlayoutEffect.o -200
JoinCallRequest.o +196
RTCAudioStore+AVAudioSessionEffect.o -192
WebRTCAudioSessionWatchdog.o -192
ProximityMonitor.o +180
Combine.tbd -180
QueryCallParticipantsResponse.o +172
RawJSON+Double.o -168
RepeatingTimerControl.o -166
RTCAudioStore+InterruptionsEffect.o -164
TimeOutError.o +158
MediaTransceiverStorage.o -152
MicrophoneManager.o +152
RTCAudioStore+DefaultReducer.o -152
ConnectionErrorEvent.o +146
Retries.o +136
IngressAudioEncodingOptionsRequest.o +132
CallController.o +129
AppUpdatedEvent.o +124
CallMemberUpdatedPermissionEvent.o +124
AVAudioSessionObserver.o +124
GoLiveRequest.o +124
StreamRuntimeCheck.o -122
ConnectionQuality.o +120
CallUserFeedbackSubmittedEvent.o +120
HTTPConfig.o -116
RingCallResponse.o +116
IngressSourceRequest.o +116
UserInfoResponse.o +116
Timer.o -113
CallSessionParticipantLeftEvent.o +112
CallEndedEvent.o +112
CustomVideoEvent.o +112
UpdatedCallPermissionsEvent.o +112
CallClosedCaptionsFailedEvent.o +112
CallMemberAddedEvent.o +112
CallMemberUpdatedEvent.o +112
PermissionRequestEvent.o +112
CallFrameRecordingStoppedEvent.o +112
CallFrameRecordingStartedEvent.o +112
CallSessionStartedEvent.o +112
CallUserMutedEvent.o +112
CallRtmpBroadcastStartedEvent.o +112
CallRtmpBroadcastStoppedEvent.o +112
CallLiveStartedEvent.o +112
CallModerationWarningEvent.o +112
BlockedUserEvent.o +112
KickedUserEvent.o +112
CallHLSBroadcastingStoppedEvent.o +112
CallHLSBroadcastingFailedEvent.o +112
CallClosedCaptionsStartedEvent.o +112
CallClosedCaptionsStoppedEvent.o +112
CallTranscriptionStoppedEvent.o +112
CallTranscriptionStartedEvent.o +112
CallTranscriptionFailedEvent.o +112
CallRecordingFailedEvent.o +112
CallModerationBlurEvent.o +112
CallRejectedEvent.o +112
CallMemberRemovedEvent.o +112
CallSettingsRequest.o +112
CallRtmpBroadcastFailedEvent.o +112
CallDeletedEvent.o +112
CallRecordingStoppedEvent.o +112
SystemEnvironment+XStreamClient.o +112
CallStatsReportReadyEvent.o +112
CallAcceptedEvent.o +112
CallHLSBroadcastingStartedEvent.o +112
CallNotificationEvent.o +112
UnblockedUserEvent.o +112
ConnectedEvent.o +112
CallMissedEvent.o +112
CallUpdatedEvent.o +112
CallRingEvent.o +112
CallReactionEvent.o +112
CallFrameRecordingFrameReadyEvent.o +112
BroadcastBufferReaderKey.o +112
CallFrameRecordingFailedEvent.o +112
CallSessionEndedEvent.o +112
CallRecordingStartedEvent.o +112
RingCallRequest.o +108
TranscriptionSettings.o +108
ICEServer.o +108
IndividualRecordingSettingsRequest.o +108
MuteUsersRequest.o +108
GeofenceSettingsRequest.o +108
RTMPSettingsRequest.o +108
TranscriptionSettingsRequest.o +108
RawRecordingSettingsResponse.o +108
BatteryStore+ObserverEffect.o +108
RecordSettingsRequest.o +108
UpdateUserPermissionsRequest.o +108
RawRecordingSettingsRequest.o +108
IngressVideoLayerRequest.o +108
HLSSettingsRequest.o +108
NoiseCancellationSettingsRequest.o +108
FrameRecordingSettingsResponse.o +108
HLSSettingsResponse.o +108
FileUploadConfig.o +108
RequestPermissionRequest.o +108
FrameRecordingSettingsRequest.o +108
GeolocationResult.o +106
AudioProcessingStore.o -106
LogFormatter.o -105
TimerControl.o -105
CallRecordingReadyEvent.o +104
CallSessionParticipantJoinedEvent.o +104
CallTranscriptionReadyEvent.o +104
UserUpdatedEvent.o +104
ClosedCaptionEvent.o +104
LockQueuing.o -102
DispatchQueueExecutor.o +100
VideoConfig.o +100
KickUserResponse.o +96
UserEventPayload.o +96
UnpinResponse.o +96
PinResponse.o +96
CompositeRecordingResponse.o +96
AudioSettingsRequest.o +96
IngressAudioEncodingResponse.o +96
Count.o +96
Coordinates.o +96
UpdateCallResponse.o +96
StopLiveResponse.o +96
SendReactionResponse.o +96
BroadcastSettingsResponse.o +96
AcceptCallResponse.o +96
GoLiveResponse.o +96
BackstageSettings.o +96
UpdateCallMembersResponse.o +96
CallClosedCaption.o +96
StartHLSBroadcastingResponse.o +96
BlockUserResponse.o +96
EgressHLSResponse.o +96
EndCallResponse.o +96
CallParticipantResponse.o +96
IngressSourceResponse.o +96
StopAllRTMPBroadcastsResponse.o +96
MediaPubSubHint.o +96
Location.o +96
UpdateUserPermissionsResponse.o +96
CreateGuestResponse.o +96
CollectUserFeedbackResponse.o +96
StartFrameRecordingResponse.o +96
CallIngressResponse.o +96
StartRTMPBroadcastsResponse.o +96
DeleteTranscriptionResponse.o +96
CallRecording.o +96
DeleteCallResponse.o +96
StopHLSBroadcastingResponse.o +96
BroadcastSettingsRequest.o +96
StartClosedCaptionsResponse.o +96
QueryMembersResponse.o +96
PublishedTrackInfo.o +96
AggregatedStats.o +96
StartTranscriptionResponse.o +96
ListRecordingsResponse.o +96
GetCallResponse.o +96
AppEventResponse.o +96
Credentials.o +96
ListTranscriptionsResponse.o +96
StopClosedCaptionsResponse.o +96
CallTranscription.o +96
WebRTCUpdateSubscriptionsAdapter.o -96
StopFrameRecordingResponse.o +96
CallStateResponseFields.o +96
StopRTMPBroadcastsResponse.o +96
RTCAudioStore+Namespace.o -96
ReportClientEventResponse.o +96
StopTranscriptionResponse.o +96
RequestPermissionResponse.o +96
DeleteRecordingResponse.o +96
CallStatsReportSummaryResponse.o +96
StartRecordingResponse.o +96
StopRecordingResponse.o +96
UnblockUserResponse.o +96
RejectCallResponse.o +96
BackstageSettingsRequest.o +96
MuteUsersResponse.o +96
SendEventResponse.o +96
HealthCheckEvent.o +92
WebRTCEvents.o +92
CallCreatedEvent.o +92
VideoSettingsRequest.o +88
RingSettings.o +88
QueryCallParticipantsRequest.o +88
RejectCallRequest.o +88
Stats.o +88
RTMPSettingsResponse.o +88
RingSettingsRequest.o +88
RecordSettingsResponse.o +88
CreateGuestRequest.o +88
StatsOptions.o +88
SFUResponse.o +88
CallTimeline.o +88
SessionSettingsRequest.o +88
ThumbnailsSettings.o +88
StopClosedCaptionsRequest.o +88
StopTranscriptionRequest.o +88
LimitsSettingsResponse.o +88
UnpinRequest.o +88
StartFrameRecordingRequest.o +88
SendEventRequest.o +88
ThumbnailsSettingsRequest.o +88
ThumbnailResponse.o +88
BlockUserRequest.o +88
RTMPIngress.o +88
DeleteCallRequest.o +88
SendReactionRequest.o +88
StartRecordingRequest.o +88
IndividualRecordingResponse.o +88
FrameRecordingResponse.o +88
RawRecordingResponse.o +88
SessionSettingsResponse.o +88
UnblockUserRequest.o +88
StartTranscriptionRequest.o +88
VideoResolution.o +88
ScreensharingSettingsRequest.o +88
KickUserRequest.o +88
IngressVideoLayerResponse.o +88
TURNAggregatedStats.o +88
PinRequest.o +88
TargetResolution.o +88
SortParamRequest.o +88
UpdateCallMembersRequest.o +88
VideoQuality.o +88
LimitsSettingsRequest.o +88
GetEdgesResponse.o +88
ScreensharingSettings.o +88
MemberRequest.o +88
PublisherAggregateStats.o +88
StartClosedCaptionsRequest.o +88
Subsession.o +88
ReactionResponse.o +88
QueryCallsResponse.o +88
QueryCallStatsResponse.o +88
StopLiveRequest.o +88
PushNotificationSettingsResponse.o +88
Call+RejectingStage.o -88
CollectUserFeedbackRequest.o +88
QueryCallStatsRequest.o +88
UpdateCallRequest.o +88
EgressRTMPResponse.o +88
JoinCallResponse.o +88
QueryMembersRequest.o +88
QueryCallsRequest.o +88
VideoSettings.o +88
RTMPBroadcastRequest.o +88
MemberResponse.o +88
UserResponse.o +88
IngressSettingsRequest.o +80
CountrywiseAggregateStats.o +80
IngressVideoEncodingOptionsRequest.o +80
IngressSettingsResponse.o +80
ReportClientEventRequest.o +80
CallResponse.o +80
DefaultAPI.o +80
IngressVideoEncodingResponse.o +80
StartRTMPBroadcastsRequest.o +80
GetOrCreateCallRequest.o +80
UserStats.o +80
SFULocationResponse.o +80
Logger+ThrowingExecution.o +76
DispatchWorkItem+TimerControl.o -76
CallKitMissingPermissionPolicy+EndCall.o -72
EgressResponse.o +72
RTCAudioStore+CallKitRecoveryMiddleware.o +72
WSEventsMiddleware.o +72
StreamCallAudioRecorder+InterruptionMiddleware.o -68
StreamCallAudioRecorder+CategoryMiddleware.o -68
CallSettingsResponse.o +64
UserSessionStats.o +64
RTCAudioStore+RouteChangeEffect.o +63
OwnCapabilitiesAudioSessionPolicy.o -56
CallsQuery.o +56
StreamVideoProcessPipeline+FilterNode.o -56
Moderation+Manager.o +50
OrderedCapacityQueue.o +44

@Stream-SDK-Bot

Copy link
Copy Markdown
Collaborator

StreamVideoSwiftUI XCSize

Object Diff (bytes)
StreamVideo.tbd -564
StreamCore_-14BA7DE23376E301_PackageProduct +564
CallViewModel.o -88

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants