Skip to content

Add local coordinator support for dev/testing#1636

Merged
aleksandar-apostolov merged 1 commit intodevelopfrom
local_cordinator_testing
Apr 1, 2026
Merged

Add local coordinator support for dev/testing#1636
aleksandar-apostolov merged 1 commit intodevelopfrom
local_cordinator_testing

Conversation

@PratimMallick
Copy link
Copy Markdown
Contributor

@PratimMallick PratimMallick commented Mar 31, 2026

Goal

Adds support for connecting the demo app to a local coordinator for development and testing. This is useful for testing SFU migration, reconnection flows, and other server-side behaviors against a local environment.

Implementation

  • Added LocalDevConfig data class in StreamVideoInitHelper that holds local coordinator address, API key, user ID, and secret. Generates HS256-signed JWT tokens from the secret automatically.

  • Added localCoordinatorAddress parameter to StreamVideoBuilder that overrides the coordinator HTTP (http://) and WebSocket (ws://) URLs when set.

  • Removed unused testSfuAddress / localSfuAddress from StreamVideoBuilder and StreamVideoClient — SFU addresses come from the coordinator's join response, so a separate override is unnecessary.

  • When LocalDevConfig is passed to loadSdk(), the demo app bypasses cloud auth, uses a local token provider for refreshes, and initializes a minimal ChatClient to prevent UI crashes.

Usage

StreamVideoInitHelper.loadSdk(
  dataStore = StreamUserDataStore.instance(),
  useRandomUserAsFallback = false,
  localDevConfig = LocalDevConfig(
      coordinatorAddress = "192.168.1.2:3030",
      apiKey = "qk4nn7rpcn75",
      secret = "vz4yhgcwums5h64uh8xbx58c9yfgtkjneab5ch9skds93xzqd8mv6dc824dusnvt",
      userId = "test-user",
  ),
)

To revert to cloud, simply remove the localDevConfig parameter.

Testing

Prerequisites: Local coordinator running at :3030 with 2 SFU instances registered.
[ ] Basic connection — App connects to local coordinator, joins a call, audio/video works
[ ] Token refresh — Kill the WebSocket, verify the SDK regenerates a local JWT (not a cloud token) and reconnects
[ ] SFU migration (GoAway) — Drain/stop SFU1 while in a call; verify the client migrates to SFU2 via the coordinator
[ ] SFU migration (connection exhaustion) — Kill SFU1 process; verify after 2 failed retries the SDK auto-escalates to migrate() and gets SFU2
[ ] No regression (cloud) — Remove localDevConfig, rebuild; verify the demo app connects to the cloud coordinator as before
[ ] Graceful failure — With only 1 SFU running, trigger migration; verify the app doesn't crash (falls back to reconnect)

☑️Contributor Checklist

General

  • I have signed the Stream CLA (required)
  • Assigned a person / code owner group (required)
  • Thread with the PR link started in a respective Slack channel (required internally)
  • PR targets the develop branch
  • PR is linked to the GitHub issue it resolves

Code & documentation

  • Changelog is updated with client-facing changes
  • New code is covered by unit tests
  • Comparison screenshots added for visual changes
  • Affected documentation updated (KDocs, docusaurus, tutorial)
  • Tutorial starter kit updated
  • Examples/guides starter kits updated (stream-video-examples)

☑️Reviewer Checklist

  • XML sample runs & works
  • Compose sample runs & works
  • Tutorial starter kit
  • Example starter kits work
  • UI Changes correct (before & after images)
  • Bugs validated (bugfixes)
  • New feature tested and works
  • Release notes and docs clearly describe changes
  • All code we touched has new or updated KDocs
  • Check the SDK Size Comparison table in the CI logs

🎉 GIF

Please provide a suitable gif that describes your work on this pull request

Summary by CodeRabbit

  • Chores
    • Improved configuration infrastructure for local development and testing scenarios.
    • Refined initialization parameters to streamline setup flow for local development environments.

Add LocalDevConfig to StreamVideoInitHelper for connecting to a local
coordinator instead of the cloud. Includes HS256 JWT token generation
from a secret, local token provider for refreshes, and minimal ChatClient
init to prevent UI crashes. The localCoordinatorAddress parameter on
StreamVideoBuilder overrides coordinator HTTP/WS URLs to use plain
http/ws. Removed unused testSfuAddress/localSfuAddress since the
coordinator's join response provides SFU addresses.

Made-with: Cursor
@PratimMallick PratimMallick requested a review from a team as a code owner March 31, 2026 07:22
@PratimMallick PratimMallick added the pr:internal Internal or infra-only changes label Mar 31, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled.

🎉 Great job! This PR is ready for review.

@github-actions
Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-video-android-core 12.00 MB 12.00 MB 0.00 MB 🟢
stream-video-android-ui-xml 5.68 MB 5.68 MB 0.00 MB 🟢
stream-video-android-ui-compose 6.27 MB 6.27 MB 0.00 MB 🟢

@sonarqubecloud
Copy link
Copy Markdown

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 31, 2026

Walkthrough

Introduced local coordinator server development support by adding a LocalDevConfig data class that handles JWT token resolution and connection parameters. Extended SDK initialization functions to optionally bypass cloud authentication and use local coordinator addresses instead of cloud services. Updated coordinator connection configuration and removed obsolete test-only parameters.

Changes

Cohort / File(s) Summary
Local Development Configuration
demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
Added LocalDevConfig data class with HMAC-SHA256 token resolution (HS256 with base64url encoding). Extended reloadSdk() and loadSdk() with optional localDevConfig parameter. When provided, bypasses cloud auth, uses local dataStore user, and passes local coordinator address and token provider to initializeStreamVideo().
Coordinator Connection Configuration
stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt
Renamed localSfuAddress constructor parameter to localCoordinatorAddress. Updated build() to resolve coordinator URLs (http:// for API, ws:// for WebSocket) from local coordinator address with fallback to cloud URLs. Passes resolved URLs to CoordinatorConnectionModule.
Client Parameter Cleanup
stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt
Removed testSfuAddress constructor parameter as local coordinator configuration is now handled upstream in StreamVideoBuilder.

Sequence Diagram(s)

sequenceDiagram
    participant App as Demo App
    participant Helper as StreamVideoInitHelper
    participant LocalConfig as LocalDevConfig
    participant DataStore as User DataStore
    participant ChatClient as ChatClient
    participant Builder as StreamVideoBuilder
    participant CoordModule as CoordinatorConnectionModule

    App->>Helper: loadSdk(dataStore, localDevConfig)
    
    alt Local Dev Config Provided
        Helper->>LocalConfig: resolveToken()
        LocalConfig->>LocalConfig: HMAC-SHA256 (HS256)
        LocalConfig-->>Helper: token
        
        Helper->>DataStore: Write local User
        Helper->>ChatClient: Initialize with DEBUG log level
        Helper->>Builder: Build with localCoordinatorAddress
        Builder->>Builder: Resolve http:// & ws:// URLs
        Builder->>CoordModule: Pass resolved coordinator URLs
        CoordModule-->>Builder: Initialized
        Builder-->>Helper: StreamVideoClient ready
    else Cloud Auth Path
        Helper->>Helper: Load user from cloud
        Helper->>ChatClient: Initialize standard
        Helper->>Builder: Build with cloud URLs
        Builder-->>Helper: StreamVideoClient ready
    end
    
    Helper-->>App: SDK initialized
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A new local path for developers to tread,
Local coordinators and tokens spread,
No clouds in the way, just local play,
Testing so simple, hip-hip-hooray! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(core): add local coordinator support for dev/testing' clearly and concisely summarizes the main change—adding local coordinator support for development and testing purposes.
Description check ✅ Passed The description includes Goal, Implementation, and Testing sections with clear explanations and usage examples, though the GIF section is unfilled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch local_cordinator_testing

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt`:
- Around line 90-96: Update the initializer in StreamVideoInitHelper to validate
the local-dev configuration up front: ensure exactly one of secret or token is
provided (reject both set), and that whichever is provided is not blank (use
trim().isNotEmpty()); additionally validate coordinator, api key and user ID
fields are non-blank so empty strings fail early. Keep resolveToken() and
generateSignedToken() behavior but rely on the stronger init checks (and use
clear require(...) messages that include which field is missing/invalid).
- Around line 83-89: The auto-generated toString() of data class LocalDevConfig
exposes secret and token; override LocalDevConfig.toString() to return a safe
representation that includes coordinatorAddress, apiKey, userId but redacts or
omits secret and token (e.g., replace with "<redacted>" or show only masked
suffix), and ensure the override is declared inside the LocalDevConfig class so
any logging or serialization uses the redacted form.

In
`@stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt`:
- Around line 237-248: The resolved API/WSS URLs built in StreamVideoBuilder
(resolvedApiUrl, resolvedWssUrl) produce malformed base URLs for
Retrofit/CoordinatorConnectionModule: the local API URL lacks a trailing slash
and the cloud fallback has an extra slash ("https:///$videoDomain"). Update the
builders so the local API URL includes a trailing slash (e.g.,
"http://${it.trimEnd('/')}/"), change the cloud API fallback to
"https://$videoDomain/" (single host, trailing slash), and verify the WSS paths
remain correct for CoordinatorConnectionModule and
Retrofit.Builder().baseUrl(...) which requires a valid host and a trailing '/'.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ab0f0742-ab2a-4c79-9a3a-e1fabe56b21d

📥 Commits

Reviewing files that changed from the base of the PR and between 9128cd3 and 920a842.

📒 Files selected for processing (3)
  • demo-app/src/main/kotlin/io/getstream/video/android/util/StreamVideoInitHelper.kt
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoBuilder.kt
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt
💤 Files with no reviewable changes (1)
  • stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/StreamVideoClient.kt

Copy link
Copy Markdown
Contributor

@aleksandar-apostolov aleksandar-apostolov left a comment

Choose a reason for hiding this comment

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

LGTM.

@aleksandar-apostolov aleksandar-apostolov merged commit fc306fb into develop Apr 1, 2026
14 of 15 checks passed
@aleksandar-apostolov aleksandar-apostolov deleted the local_cordinator_testing branch April 1, 2026 07:43
@aleksandar-apostolov aleksandar-apostolov changed the title feat(core): add local coordinator support for dev/testing Add local coordinator support for dev/testing Apr 1, 2026
@stream-public-bot stream-public-bot added the released Included in a release label Apr 1, 2026
@stream-public-bot
Copy link
Copy Markdown
Collaborator

🚀 Available in v1.21.0

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

Labels

pr:internal Internal or infra-only changes released Included in a release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants