Skip to content

Conversation

xsahil03x
Copy link
Member

@xsahil03x xsahil03x commented Sep 27, 2025

Submit a pull request

Fixes: FLU-241

Description of the pull request

This commit introduces a new messageCount field to the ChannelModel and Event classes.

This field represents the total number of messages in a channel and is populated when the count_messages option is enabled for the app.

The channel state is now updated to reflect changes in messageCount by listening to channel events.

Summary by CodeRabbit

  • New Features
    • Channel message count exposed with a reactive stream and updates in real time when enabled.
  • Persistence
    • Message counts are persisted locally for faster access and reliability.
  • Tests
    • Added tests covering live updates, count changes from new/deleted messages, mapping, and preserved channel properties.
  • Documentation
    • CHANGELOGs updated to note message count support.
  • Chores
    • Local database schema version bumped to support message count storage.

This commit introduces a new `messageCount` field to the `ChannelModel` and `Event` classes.

This field represents the total number of messages in a channel and is populated when the `count_messages` option is enabled for the app.

The channel state is now updated to reflect changes in `messageCount` by listening to channel events.
This commit introduces two new properties to the `Channel` class:
- `messageCount`: An integer representing the number of messages in the channel.
- `messageCountStream`: A stream that emits the message count whenever it changes.

These properties are only populated if the `count_messages` option is enabled for the app.
This commit introduces the `messageCount` field to the `ChannelEntity` in the persistence layer.

This change includes:
- Adding the `messageCount` column to the `Channels` table definition.
- Incrementing the database schema version to 24.
- Updating the `ChannelMapper` to include `messageCount` in mappings between `Channel` and `ChannelEntity`.
- Regenerating the `drift_chat_database.g.dart` file to reflect the schema changes.
- Updating the changelog.
- Updating tests to include `messageCount`.
Copy link
Contributor

coderabbitai bot commented Sep 27, 2025

Walkthrough

Adds channel-level message count support: new messageCount and messageCountStream on Channel, Event carries channelMessageCount, ChannelClientState listens for channelMessageCount events to update channel state, persistence schema and mappers updated (Drift schema bumped to 24), and tests added/updated.

Changes

Cohort / File(s) Summary
Client: Channel + tests
packages/stream_chat/lib/src/client/channel.dart, packages/stream_chat/test/src/client/channel_test.dart
Channel exposes int? messageCount and Stream<int?> messageCountStream. ChannelClientState adds a private listener for channelMessageCount events and updates channel state; tests verify event-driven updates, sequences with messageNew/messageDeleted, property preservation, and stream emissions.
Core models: ChannelModel
packages/stream_chat/lib/src/core/models/channel_model.dart, .../channel_model.g.dart
Adds final int? messageCount to ChannelModel, includes it in constructor, copyWith, merge; marks with @JsonKey(includeToJson: false) and registers 'message_count' in topLevelFields; deserializes from message_count.
Core models: Event
packages/stream_chat/lib/src/core/models/event.dart, .../event.g.dart
Adds final int? channelMessageCount to Event, includes in constructor and copyWith, registers 'channel_message_count' in topLevelFields, and wires JSON (de)serialization under channel_message_count.
Persistence: schema + generated DB
packages/stream_chat_persistence/lib/src/entity/channels.dart, .../db/drift_chat_database.dart, .../db/drift_chat_database.g.dart
Adds nullable messageCount column (message_count) to Channels table, threads it through generated code (ChannelEntity, ChannelsCompanion, table columns, mapping, toJson/fromJson), and bumps Drift schemaVersion 23 → 24.
Persistence: mapper + tests
packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart, .../test/src/mapper/channel_mapper_test.dart
Propagates messageCount between ChannelEntity and ChannelModel (both directions); tests updated to assert propagation and consistency during mappings.
Docs/Changelog
packages/stream_chat_persistence/CHANGELOG.md, packages/stream_chat/CHANGELOG.md
Notes upcoming support for Channel.messageCount.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor WS as WebSocket
  participant CCS as ChannelClientState
  participant CS as Channel State
  participant C as Channel
  participant S as Subscribers

  WS->>CCS: event(channel_message_count = N)
  note right of CCS #DDEEDF: _listenChannelMessageCount invoked during init
  CCS->>CS: updateChannelState(messageCount: N)
  CS->>C: copyWith(messageCount: N)
  C-->>S: messageCountStream emits N
Loading
sequenceDiagram
  autonumber
  participant DB as Drift (schema v24)
  participant Entity as ChannelEntity
  participant Mapper as ChannelMapper
  participant Model as ChannelModel

  DB-->>Entity: read row (message_count -> messageCount)
  Entity->>Mapper: toChannelModel()
  Mapper-->>Model: set messageCount

  Model->>Mapper: toEntity()
  Mapper-->>Entity: include messageCount
  Entity-->>DB: write row (message_count)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • renefloor
  • Brazol

Poem

A whisker-twitch, a count appears—
Events hop in and clear the haze.
Streams ripple numbers, soft and bright,
DB burrow stores them safe at night.
Rabbit hops on—more counts, hooray! 🐇📬

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “feat(llc, persistence): add messageCount to channel model and event” clearly and concisely highlights the addition of the messageCount feature across both the client and persistence layers, reflecting the primary change implemented in this PR. It avoids unnecessary detail while indicating the relevant components impacted, making it immediately understandable to reviewers and team members scanning the commit history. The scope prefix “llc, persistence” accurately signals the affected packages without introducing noise or unrelated information.
Linked Issues Check ✅ Passed All additions in the PR directly fulfill FLU-241 by exposing messageCount on ChannelModel and Event, wiring JSON (de)serialization, updating channel state in response to count-related events, and persisting the new field via schema migration and entity–model mappings. The client layer now listens for channelMessageCount events to update the count, and persistence updates ensure the database schema and ORM mappings include the new column. Tests validate dynamic updates from both server count events and message lifecycle events, confirming end-to-end compliance with the objective to maintain per-channel message counts.
Out of Scope Changes Check ✅ Passed All code changes relate directly to the addition and management of the messageCount feature as specified in FLU-241, including field declarations, event handling, database schema version bump, and mapping updates. There are no unrelated modifications or extraneous refactorings outside the scope of per-channel message counting. Changelog updates, schema migrations, and test additions all support the core objective without introducing off-topic changes.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/channel-message-count

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

github-actions bot commented Sep 27, 2025

⚠️ Database Entity Files Modified

The following database entity files have been modified in this PR:

packages/stream_chat_persistence/lib/src/entity/channels.dart

📝 Remember to:

  1. Update database version in db/drift_chat_database.dart.
  2. Update entity schema tests if necessary.

Note: This comment is automatically generated by the CI workflow.

@xsahil03x xsahil03x changed the title feat(llc): add messageCount to channel model and event feat(llc, persistence): add messageCount to channel model and event Sep 27, 2025
Copy link
Contributor

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart (1)

58-73: Schema bump triggers destructive migration — prefer additive migration

Bumping to 24 currently wipes all tables on upgrade. This will drop persisted channels/messages for apps upgrading. Add a targeted migration for message_count instead of full rebuild.

   @override
   MigrationStrategy get migration => MigrationStrategy(
     beforeOpen: (details) async {
       await customStatement('PRAGMA foreign_keys = ON');
     },
     onUpgrade: (migrator, from, to) async {
-      if (from != to) {
-        for (final table in allTables) {
-          await migrator.deleteTable(table.actualTableName);
-        }
-        await migrator.createAll();
-      }
+      // Additive migrations first
+      if (from < 24) {
+        // Add `message_count` to Channels without data loss
+        await migrator.addColumn(channels, channels.messageCount);
+      }
+      // Keep the destructive fallback only for future breaking changes
+      // where additive migration isn't feasible.
+      // if (from != to) {
+      //   for (final table in allTables) {
+      //     await migrator.deleteTable(table.actualTableName);
+      //   }
+      //   await migrator.createAll();
+      // }
     },
   );

Also document this in the CHANGELOG/upgrade notes if you intentionally keep the destructive path.

🧹 Nitpick comments (3)
packages/stream_chat_persistence/CHANGELOG.md (1)

1-3: Add note about the Drift schema bump.

Persistence consumers will need to know that the Drift schema version jumped to 24 for the new message_count column. Please mention the schema bump (and migration implications, if any) in this Upcoming entry so upgrade steps are clear.

packages/stream_chat/lib/src/core/models/channel_model.g.dart (1)

45-52: Serialization asymmetry is intentional — verify tests cover it

toJson omits message_count. Ensure tests assert that message_count is not emitted when serializing ChannelModel.

packages/stream_chat/test/src/client/channel_test.dart (1)

5773-5799: Reactive stream assertions (LGTM) — add one more case?

Nice sequence check. Consider adding a case for notification.message_new carrying channelMessageCount to ensure parity.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 008bece and 00404c0.

📒 Files selected for processing (12)
  • packages/stream_chat/lib/src/client/channel.dart (3 hunks)
  • packages/stream_chat/lib/src/core/models/channel_model.dart (6 hunks)
  • packages/stream_chat/lib/src/core/models/channel_model.g.dart (1 hunks)
  • packages/stream_chat/lib/src/core/models/event.dart (5 hunks)
  • packages/stream_chat/lib/src/core/models/event.g.dart (2 hunks)
  • packages/stream_chat/test/src/client/channel_test.dart (1 hunks)
  • packages/stream_chat_persistence/CHANGELOG.md (1 hunks)
  • packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart (1 hunks)
  • packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart (33 hunks)
  • packages/stream_chat_persistence/lib/src/entity/channels.dart (1 hunks)
  • packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart (2 hunks)
  • packages/stream_chat_persistence/test/src/mapper/channel_mapper_test.dart (5 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-25T08:19:01.469Z
Learnt from: xsahil03x
PR: GetStream/stream-chat-flutter#2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message with MessageSendingStatus.failed or MessageSendingStatus.failed_update status, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.

Applied to files:

  • packages/stream_chat/lib/src/client/channel.dart
📚 Learning: 2025-09-25T08:19:01.469Z
Learnt from: xsahil03x
PR: GetStream/stream-chat-flutter#2394
File: packages/stream_chat_flutter/lib/src/message_action/message_actions_builder.dart:82-92
Timestamp: 2025-09-25T08:19:01.469Z
Learning: In the Stream Chat Flutter library, when deleting a message that hasn't been sent to the server yet (message.remoteCreatedAt == null) or is bounced with error, the _deleteMessage method in channel.dart automatically handles deletion locally via _deleteLocalMessage without making API calls, preventing 404 errors and deletingFailed states.

Applied to files:

  • packages/stream_chat/lib/src/client/channel.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: stream_chat_persistence
  • GitHub Check: stream_chat
  • GitHub Check: stream_chat_localizations
  • GitHub Check: stream_chat_flutter_core
  • GitHub Check: stream_chat_flutter
  • GitHub Check: analyze_legacy_versions
  • GitHub Check: build (android)
  • GitHub Check: build (ios)
  • GitHub Check: analyze
  • GitHub Check: test
🔇 Additional comments (12)
packages/stream_chat/lib/src/core/models/channel_model.g.dart (1)

42-43: Read-only JSON ingestion for messageCount (LGTM) — confirm annotations

messageCount is parsed from message_count and excluded from toJson (expected, server-managed). Please confirm the source ChannelModel.messageCount has @JsonKey(includeToJson: false) and that ChannelModel.topLevelFields includes 'message_count' in channel_model.dart.

packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart (2)

18-19: Entity → Model propagation (LGTM)

Correctly maps messageCount to ChannelModel.


59-60: Model → Entity propagation (LGTM)

Round‑trip mapping preserved.

packages/stream_chat/test/src/client/channel_test.dart (3)

5656-5676: Event-sourced update from channelMessageCount (LGTM)

Covers the primary flow.


5680-5729: Increment/decrement via message.new/deleted (LGTM)

Good coverage of both directions.


5733-5769: Property preservation while updating count (LGTM)

Validates non-regression on unrelated fields.

packages/stream_chat/lib/src/core/models/event.g.dart (1)

79-129: Serialization round-trip updated cleanly.

Great to see channel_message_count wired through both fromJson and toJson—this will keep the field flowing without disturbing existing payloads.

packages/stream_chat/lib/src/core/models/event.dart (1)

166-211: New event surface area is consistent.

Adding channelMessageCount to the model, top-level whitelist, and copyWith keeps the API coherent and ensures serializers don’t drop the new value.

packages/stream_chat/lib/src/client/channel.dart (2)

419-435: Channel accessors stay in sync.

Exposing messageCount and its stream alongside the existing getters keeps the public API uniform—nice touch documenting the count_messages prerequisite.


2370-2385: Listener cleanly propagates count updates.

Subscribing to all channel events and short-circuiting on null keeps the handler cheap while guaranteeing we persist the new count through updateChannelState.

packages/stream_chat_persistence/test/src/mapper/channel_mapper_test.dart (1)

25-123: Persistence coverage looks solid.

The added expectations for messageCount across entity↔model↔state mappings give good confidence the new column won’t regress silently.

packages/stream_chat/lib/src/core/models/channel_model.dart (1)

34-264: Channel model integration is well-rounded.

Constructor, JSON surface, copyWith, and merge all account for messageCount, so downstream consumers get the field without leaking it back to writes.

Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
packages/stream_chat/CHANGELOG.md (1)

5-5: Document all new public surfaces

PR adds Channel.messageCountStream and Event.channelMessageCount, but the changelog only mentions Channel.messageCount. Please list the other new entry points so downstream integrators know about them when scanning release notes.

-- Added support for `Channel.messageCount` field.
+- Added support for `Channel.messageCount` and `Channel.messageCountStream`.
+- Added `Event.channelMessageCount` to surface channel-level counts in event payloads.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 00404c0 and 17c83bd.

📒 Files selected for processing (1)
  • packages/stream_chat/CHANGELOG.md (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build (android)
  • GitHub Check: build (ios)
  • GitHub Check: test
  • GitHub Check: analyze_legacy_versions

Copy link

codecov bot commented Sep 28, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 63.91%. Comparing base (008bece) to head (17c83bd).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2403      +/-   ##
==========================================
+ Coverage   63.84%   63.91%   +0.06%     
==========================================
  Files         413      413              
  Lines       25862    25881      +19     
==========================================
+ Hits        16511    16541      +30     
+ Misses       9351     9340      -11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant