Skip to content

feat(bridge): batch rapid-fire IM messages for same session#265

Open
lowmiaq-gmail wants to merge 1 commit intoop7418:mainfrom
lowmiaq-gmail:feat/bridge-message-batching
Open

feat(bridge): batch rapid-fire IM messages for same session#265
lowmiaq-gmail wants to merge 1 commit intoop7418:mainfrom
lowmiaq-gmail:feat/bridge-message-batching

Conversation

@lowmiaq-gmail
Copy link

Summary

When a user sends multiple messages quickly from an IM channel (Feishu, Telegram, Discord), they are now aggregated into a single Claude prompt instead of being queued for serial one-by-one processing.

Problem

  • Messages for the same session are serialized via processWithSessionLock — each Claude call takes 30s–5min, so message 2 waits for message 1 to fully complete
  • No acknowledgment is sent for queued messages, making users think messages were lost
  • Rapid-fire messages create a long serial queue, degrading UX significantly

Solution

  • Message batching: Add pendingBatches Map to BridgeManagerState for per-session message aggregation
  • Queue acknowledgment: Send immediate "⏳ Message received (#N in queue)" reply so users know their message wasn't lost
  • Batch window: 2-second BATCH_WINDOW_MS allows collecting multiple rapid-fire messages before flushing
  • Auto-flush: processWithSessionLock.finally() automatically flushes any messages that accumulated during processing

Behavior

Scenario Before After
Single message, session free Processed immediately No change
3 messages sent rapidly while session busy Serial processing (3x latency), no feedback Batched into 1 prompt + ack per message
Messages during long Claude call Silently queued, user thinks lost Immediate "received" reply

Key functions added

  • scheduleOrProcess() — routes messages to direct processing or batch queue
  • flushBatch() — merges queued messages (text joined with --- separators, attachments concatenated) into a single handleMessage call
  • PendingBatch interface + BATCH_WINDOW_MS constant

Testing

  • TypeScript type-check passes (tsc --noEmit)
  • Single message path unchanged (no regression)
  • Batch path: multiple messages merged with --- separator, attachments concatenated

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

When a user sends multiple messages quickly from an IM channel (Feishu,
Telegram, Discord), they are now aggregated into a single Claude prompt
instead of being queued for serial one-by-one processing.

Problem:
- Messages for the same session were serialized via processWithSessionLock
- Each Claude call takes 30s-5min, so message 2 waited for message 1
- No acknowledgment was sent, making users think messages were lost

Solution:
- Add pendingBatches Map to BridgeManagerState for per-session aggregation
- scheduleOrProcess() checks if session has active lock; if busy, buffers
  the message and sends an immediate "⏳ received" acknowledgment
- 2-second batch window (BATCH_WINDOW_MS) allows collecting multiple
  rapid-fire messages before flushing
- flushBatch() merges queued messages into a single prompt with ---
  separators, concatenates attachments, and processes as one request
- processWithSessionLock.finally() auto-flushes any messages that
  accumulated during processing

Behavior:
- Single message, session free → processed immediately (no change)
- Multiple messages while session busy → batched + ack sent per message
- Batch flushed after 2s window or when current processing completes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Mar 13, 2026

Someone is attempting to deploy a commit to the op7418's projects Team on Vercel.

A member of the Team first needs to authorize it.

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