Skip to content

Add MessageBufferingConfig to allow custom back-pressure config for message.new events#6406

Draft
VelikovPetar wants to merge 2 commits into
v6from
feature/AND-1166_add_buffering_support_for_message_new
Draft

Add MessageBufferingConfig to allow custom back-pressure config for message.new events#6406
VelikovPetar wants to merge 2 commits into
v6from
feature/AND-1166_add_buffering_support_for_message_new

Conversation

@VelikovPetar
Copy link
Copy Markdown
Contributor

@VelikovPetar VelikovPetar commented May 1, 2026

Goal

High-traffic channel types (e.g. livestreams) can produce a flood of message.new events that arrive faster than the sequential event-handling pipeline can process them. The current implementation funnels every socket event through a single MutableSharedFlow with extraBufferCapacity = Int.MAX_VALUE, which means there is no back-pressure: a burst of new-message events queues up unbounded memory and starves more important signals (reads, bans, member updates) of timely processing.

This PR introduces a MessageBufferConfig that lets integrators opt specific channel types into a bounded buffer for NewMessageEvents, with a configurable overflow strategy (SUSPEND / DROP_OLDEST / DROP_LATEST). Signal-critical events and events for non-opted-in channel types are unaffected.

Implementation

  • Added MessageBufferConfig (under MessageLimitConfig.messageBufferConfig) exposing:
    • channelTypes: Set<String> — channel types whose NewMessageEvents go through the bounded buffer (empty by default → feature is a no-op).
    • capacity: Int — buffer capacity (defaults to Int.MAX_VALUE).
    • overflow: BufferOverflow — overflow strategy (defaults to SUSPEND).
  • EventHandlerSequential now allocates a secondary MutableSharedFlow (bufferedNewMessageEvents) lazily, only when buffering is enabled, so the default configuration pays no cost for it.
  • Two listener variants:
    • defaultSocketEventListener — the existing unbuffered path; used when no channel types are opted in.
    • bufferedSocketEventListener — routes NewMessageEvents for opted-in channel types to the bounded flow, and everything else (including non-opted-in NewMessageEvents and all other event types) to the unbuffered flow.
  • startListening() picks the listener based on bufferConfig.channelTypes.isNotEmpty() and only collects from bufferedNewMessageEvents when buffering is enabled.
  • StreamStatePluginFactory wires the config from StatePluginConfig.messageLimitConfig.messageBufferConfig into EventHandlerSequential.

The bounded flow shares the same downstream pipeline (socketEventCollectorhandleBatchEvent) as the unbuffered flow, so ordering inside each flow is preserved and back-pressure is applied independently per flow.

Testing

  • Added 200+ lines of unit tests in EventHandlerSequentialTest covering:
    • default behaviour (no buffering) is unchanged when channelTypes is empty.
    • NewMessageEvents for opted-in channel types are routed through the bounded buffer.
    • NewMessageEvents for non-opted-in channel types and all non-NewMessageEvent events keep using the unbuffered path.
    • DROP_OLDEST / DROP_LATEST / SUSPEND overflow strategies behave as expected when the buffer is full.
  • Existing tests (TotalUnreadCountTest, EventHandlerSequentialUserMessagesDeletedTest) updated to pass the new bufferConfig argument.

@VelikovPetar VelikovPetar added the pr:new-feature New feature label May 1, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 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 (or ignored for dependabot PRs).

🎉 Great job! This PR is ready for review.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.26 MB 5.26 MB 0.00 MB 🟢
stream-chat-android-offline 5.49 MB 5.49 MB 0.00 MB 🟢
stream-chat-android-ui-components 10.64 MB 10.65 MB 0.00 MB 🟢
stream-chat-android-compose 12.87 MB 12.87 MB 0.00 MB 🟢

@github-actions
Copy link
Copy Markdown
Contributor

This pull request has been automatically marked as stale because it has been inactive for 14 days. It will be closed in 7 days if no further activity occurs.

@github-actions github-actions Bot added the Stale label May 18, 2026
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
76.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant