Skip to content

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

Draft
VelikovPetar wants to merge 1 commit intov6from
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 1 commit intov6from
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.

🎉 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 🟢

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 1, 2026

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

pr:new-feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant