Skip to content

Migrate the thread, unread and mute notification events to the generated event models - #6771

Open
gpunto wants to merge 1 commit into
developfrom
migrate/notification-state-events
Open

gpunto wants to merge 1 commit into
developfrom
migrate/notification-state-events

Conversation

@gpunto

@gpunto gpunto commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Goal

Parse the notification.thread_message_new, notification.mark_unread, notification.mutes_updated and notification.channel_mutes_updated events with the generated event models.

Part of AND-1291

Implementation

  • Vendor the generated NotificationThreadMessageNewEvent, NotificationMarkUnreadEvent, NotificationMutesUpdatedEvent and NotificationChannelMutesUpdatedEvent, and delete the hand-written DTOs.
  • The adapters require the fields the spec marks optional but the domain events need (the cid and thread unread counts on notification.thread_message_new; the cid, user, first unread message, last read date and unread messages on notification.mark_unread), and reject an event missing one.
  • notification.thread_message_new maps its channel and message with the generated channel and message mappers, and the mute events map me with the generated own user mapper.

Testing

GeneratedNotificationStateEventParsingTest covers each event, a nanosecond created_at, and a missing required field.

On a device: received a new thread reply notification, a channel and a thread marked unread, and a user and a channel muted. Each event carried the right channel, message, user, unread counts and mutes.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of notification events for mute updates, marking messages as unread, and new thread messages.
    • Preserved event timestamps and unread counts when processing these updates, with missing optional unread totals defaulting to zero.

@gpunto gpunto added the pr:internal Internal changes / housekeeping label Oct 2, 2026
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

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, or the PR is bot-authored.
  • An issue is linked (Linear ticket or GitHub issue), or the PR is bot-authored.

🎉 Great job! This PR is ready for review.

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 6.17 MB 6.18 MB 0.00 MB 🟢
stream-chat-android-ui-components 11.48 MB 11.48 MB 0.00 MB 🟢
stream-chat-android-compose 13.14 MB 13.15 MB 0.00 MB 🟢

@sonarqubecloud

sonarqubecloud Bot commented Oct 2, 2026

Copy link
Copy Markdown

@gpunto
gpunto marked this pull request as ready for review October 2, 2026 09:51
@gpunto
gpunto requested a review from a team as a code owner October 2, 2026 09:51
@gpunto
gpunto enabled auto-merge October 2, 2026 09:51
@coderabbitai

coderabbitai Bot commented Oct 2, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 4b053783-4f5b-481e-a752-44971af93d8a

📥 Commits

Reviewing files that changed from the base of the PR and between 63fb9a9 and 06d4338.

📒 Files selected for processing (11)
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/EventMapping.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/EventAdapter.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/NotificationChannelMutesUpdatedEvent.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/NotificationMarkUnreadEvent.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/NotificationMutesUpdatedEvent.kt
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/NotificationThreadMessageNewEvent.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/EventChatJsonProvider.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/EventMappingTestArguments.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser/EventArguments.kt
  • stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/GeneratedNotificationStateEventParsingTest.kt
💤 Files with no reviewable changes (1)
  • stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.


Walkthrough

Four notification event types now use generated network models for parsing and domain mapping. The change removes their dedicated DTOs and updates event adapters, mappings, and test fixtures.

Changes

Notification event migration

Layer / File(s) Summary
Generated event models and parsing
stream-chat-android-client/src/main/java/io/getstream/chat/android/network/models/Notification*Event.kt, stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/EventAdapter.kt, stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt
Four generated models define notification event fields and event types. Parser adapters use those models and check required fields where specified. The four replaced DTO declarations are removed.
Domain event mapping
stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/EventMapping.kt
Generated-event dispatch maps the four notification models to domain events. The mappings derive channel identifiers, copy event fields, and apply defaults to specified unread counts.
Fixtures and parsing tests
stream-chat-android-client/src/test/java/io/getstream/chat/android/client/EventChatJsonProvider.kt, stream-chat-android-client/src/test/java/io/getstream/chat/android/client/api2/mapping/EventMappingTestArguments.kt, stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser/EventArguments.kt, stream-chat-android-client/src/test/java/io/getstream/chat/android/client/parser2/GeneratedNotificationStateEventParsingTest.kt
Mapping fixtures use generated event models. Parsing tests check event types, timestamp values, and errors for missing required fields. The thread-message-new fixtures include message and thread identifiers and updated message and channel data.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Refactor

Suggested reviewers: velikovpetar

Merge Risk: ⚪ Minimal · up to 06d43

The migrated notification events preserve the expected data for the inspected payloads, with no identified issue that needs to be fixed before merging.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 06d43

The existing notification delivery path and user identity checks remain in place. The main uncertainty is compatibility: stricter payload requirements can reject notifications previously accepted, and complete recovery from missed or repeated events is not established.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The demonstrated exposure is the connected client's notification and user/channel state handling. The inspected migration does not add a remote entrypoint: events still arrive through the existing socket path, and channel notification subscriptions still filter by cid. Server-side event provenance and authorization are outside the available evidence.

Trust Boundaries and Controls

  • observed — Presence validation protects domain construction, not event authorization. The existing client logic trusts HasOwnUser snapshots, while ordinary UserEvent data is merged only when its user ID matches the current user. The migration retains that distinction.

Resilience and Maintainability Implications

  • observed — Client event handling is serialized by a mutex, mute events replace a snapshot rather than incrementing state, and ConnectedEvent installs a received user snapshot. These controls support local serialization and repeated identical snapshot application, but do not prove stale-event ordering or complete unread/thread recovery after interruption.
  • observed — Rejected payloads enter the existing network-error handling path. Consequently, stricter contract rejection has consequences beyond an omitted domain event; compatibility with actual backend payload variants remains material to failure containment.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 25 functions across 10 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the migration of thread, unread, and mute notification events to generated event models.
Description check ✅ Passed The description includes the required Goal, Implementation, and Testing sections. It explains the migration, required fields, mapping behavior, automated tests, and device validation. UI details, chec…
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.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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

A rabbit checks each event’s name,
Then maps its fields through a new frame.
Unread counts and threads appear,
Timestamps keep their details clear.
Four parsed events hop into view.

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

@aleksandar-apostolov aleksandar-apostolov 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.

The generated NotificationThreadMessageNewEvent makes message_id, thread_id and watcher_count required, and the fixture had to grow all three — but none of them reach the domain event. Does that mean a notification.thread_message_new missing any one of them now gets dropped instead of mapped? If the spec marks them required because feeds share the event, would defaulting the ones we don't read be safer?

@gpunto

gpunto commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

message_id, thread_id and watcher_count are always on the wire for this event. In the backend's NotificationThreadMessageNewEvent they're a plain string, string and int without omitempty, so the chat backend can't leave them out. The E2E mock never sends this event, so nothing changes there.

We decided to keep the generated models strict on Android and fix the producer when one is wrong, rather than default fields. None of the three reach the domain event, so a default wouldn't change what apps see; it would only hide a producer sending a malformed event.

This branch has not been deployed

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

Labels

pr:internal Internal changes / housekeeping

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants