Accept RFC3339 date strings on internal WS events#71
Conversation
The video coordinator gateway sends dates as RFC3339 strings (connection.ok: "created_at": "2026-07-06T07:47:26.592958Z" at $.me.created_at), but DateMillisAdapter only accepted epoch millis. The internal parse of the handshake event failed, the composite serializer fell back to a null external serializer, and every StreamClient.connect() against such a gateway died with 'No external serializer available' - the video SDK coordinator socket could never connect on a device. Replace DateMillisAdapter with LenientDateAdapter: writes stay epoch millis (outbound wire format unchanged), reads accept both epoch millis numbers and RFC3339 strings.
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
|
WalkthroughThe PR replaces Moshi's ChangesLenient Date Adapter
Estimated code review effort: 2 (Simple) | ~12 minutes Sequence Diagram(s)sequenceDiagram
participant Server as WebSocket Frame
participant Moshi as Moshi
participant Adapter as LenientDateAdapter
participant Rfc3339 as Rfc3339DateJsonAdapter
participant Model as Event Model
Server->>Moshi: JSON payload with date field
Moshi->>Adapter: fromJson(reader)
alt token is NUMBER
Adapter->>Adapter: Date(millis)
else token is STRING
Adapter->>Rfc3339: fromJson(reader)
Rfc3339-->>Adapter: parsed Date
else other token
Adapter-->>Moshi: throw JsonDataException
end
Adapter-->>Moshi: Date result
Moshi-->>Model: populated Date field
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
stream-android-core/src/main/java/io/getstream/android/core/internal/serialization/moshi/StreamCoreMoshiProvider.kt (1)
34-59: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueCorrect lenient parsing logic.
fromJson/toJsoncorrectly handle NULL/NUMBER/STRING tokens, delegate string parsing toRfc3339DateJsonAdapter, and preserve epoch-millis on write. VerifiedRfc3339DateJsonAdapter.fromJsontruncates fractional seconds beyond milliseconds without throwing, andJsonWriter.value(Number)correctly writesnullfor a null boxedLong, so the round-trip and null-handling behavior in the tests is well-founded.One minor nit: the KDoc states this is the "Adapter for
[Date]fields on internal WS events," but it's registered inbuilder()forDate::class.javaglobally, so it applies to everyDatefield serialized/deserialized through this Moshi instance (e.g.StreamConnectedUserin REST-style models), not just internal WS events. Worth tightening the wording to avoid future confusion about scope.✏️ Suggested doc tweak
/** - * Adapter for [Date] fields on internal WS events. + * Adapter for [Date] fields registered on the shared Moshi instance (used by internal WS + * events as well as other models such as [StreamConnectedUser]). *🤖 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 `@stream-android-core/src/main/java/io/getstream/android/core/internal/serialization/moshi/StreamCoreMoshiProvider.kt` around lines 34 - 59, The KDoc on LenientDateAdapter describes it as only for internal WS events, but StreamCoreMoshiProvider.builder() registers it for Date::class.java on the Moshi instance globally. Update the documentation near LenientDateAdapter to reflect the actual scope of use across all Date fields handled by this provider, so it matches how fromJson/toJson are applied.
🤖 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.
Nitpick comments:
In
`@stream-android-core/src/main/java/io/getstream/android/core/internal/serialization/moshi/StreamCoreMoshiProvider.kt`:
- Around line 34-59: The KDoc on LenientDateAdapter describes it as only for
internal WS events, but StreamCoreMoshiProvider.builder() registers it for
Date::class.java on the Moshi instance globally. Update the documentation near
LenientDateAdapter to reflect the actual scope of use across all Date fields
handled by this provider, so it matches how fromJson/toJson are applied.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 237a4661-ab89-487f-a6ef-dac73b48e618
📒 Files selected for processing (3)
stream-android-core/src/main/java/io/getstream/android/core/internal/serialization/moshi/StreamCoreMoshiProvider.ktstream-android-core/src/test/java/io/getstream/android/core/internal/serialization/moshi/MoshiProviderTest.ktstream-android-core/src/test/java/io/getstream/android/core/internal/serialization/moshi/StreamCoreMoshiProviderDateParsingTest.kt
|
🚀 Available in v5.0.1 |



Goal
Fixes AND-1295 —
StreamClient.connect()fails permanently against the video coordinator: the gateway sends dates as RFC3339 strings, but the internal Moshi'sDateMillisAdapteronly accepts epoch millis. Theconnection.okhandshake parse throws (Expected a long but was 2026-07-06T07:47:26.592958Z at path $.me.created_at), the composite serializer falls back to a null external serializer (No external serializer available), and the socket loopsOpening → Authenticating → Disconnectedforever. Not fixable product-side:StreamClientConnectedEventis internal andStreamSocketSessiontype-matches on it.Implementation
DateMillisAdapterwithLenientDateAdapterinStreamCoreMoshiProvider: reads accept both epoch-millis numbers and RFC3339 strings (delegating to Moshi'sRfc3339DateJsonAdapter, already a dependency); writes stay epoch millis, so the outbound wire format is unchanged.internal. Millis payloads parse identically to 5.0.0; only previously-failing string payloads gain a successful parse, so existing consumers (Feeds) are unaffected. Safe as a 5.0.1 patch.Testing
StreamCoreMoshiProviderDateParsingTest: parses the realconnection.okframe captured from the video coordinator handshake (RFC3339, sub-millisecond precision), epoch-millis backward-compat, millis-on-write assertion, round-trip, invalid-token failure.:stream-android-core:testDebugUnitTest: 731 tests, 730 green — the 1 failure (StreamCompositeEventSerializationImplTest, reflection ondeclaredConstructors.first()) fails identically on cleandevelop; pre-existing flake, unrelated.Checklist
Summary by CodeRabbit