# Message Queue Fix: Handling Early Messages ## The Problem Messages were being dropped with the warning: ``` ⚠️ Remote channel full, dropping message (this shouldn't happen) ``` But the Remote channel wasn't actually "full" - it **wasn't ready yet**. ### Root Cause: Timing Issue Looking at the logs: ``` 17:09:02 🎧 [KOSMI WEBSOCKET] Message listener started 17:09:09 📨 Received message from Kosmi 17:09:09 ⚠️ Remote channel full, dropping message 17:09:17 Connection succeeded (IRC) ← 15 seconds later! ``` **The problem**: Kosmi connects and starts receiving messages BEFORE other bridges (like IRC) are connected and the Matterbridge router is fully set up. The `b.Remote` channel exists but isn't being read yet, so our non-blocking send fails. ## The Solution Added a **message queue** to buffer messages that arrive before the Remote channel is ready. ### How It Works 1. **Try to send immediately** using non-blocking `select` 2. **If channel not ready**: Queue the message in memory 3. **On next successful send**: Flush all queued messages 4. **Also try flushing in background** goroutine ### Implementation ```go type Bkosmi struct { // ... existing fields ... messageQueue []config.Message // Buffer for early messages queueMutex sync.Mutex // Protect the queue } func (b *Bkosmi) handleIncomingMessage(payload *NewMessagePayload) { // ... create rmsg ... // Try to send to Remote channel select { case b.Remote <- rmsg: // Success! Also flush any queued messages b.flushMessageQueue() default: // Channel not ready - queue the message b.queueMutex.Lock() b.messageQueue = append(b.messageQueue, rmsg) b.queueMutex.Unlock() // Try to flush in background go b.flushMessageQueue() } } func (b *Bkosmi) flushMessageQueue() { // Try to send all queued messages // Stop if channel becomes full again // Keep remaining messages in queue } ``` ## Why This Works 1. **No messages are lost** - They're buffered in memory until the router is ready 2. **Non-blocking** - Uses goroutines and non-blocking selects throughout 3. **Automatic retry** - Every successful send triggers a flush attempt 4. **Thread-safe** - Uses mutex to protect the queue ## Expected Behavior After Fix ### Before ``` 17:09:09 Received message from Kosmi: lo 17:09:09 ⚠️ Remote channel full, dropping message 17:09:24 Received message from Kosmi: lo 17:09:24 ⚠️ Remote channel full, dropping message ``` ### After ``` 17:09:09 Received message from Kosmi: lo 17:09:09 📦 Remote channel not ready, queued message (1 in queue) 17:09:24 Received message from Kosmi: lo 17:09:24 📦 Remote channel not ready, queued message (2 in queue) 17:09:30 ✅ Message forwarded to Matterbridge 17:09:30 📤 Attempting to flush 2 queued messages 17:09:30 ✅ Flushed all 2 queued messages ``` ## Why This Happened When we added authentication and made other changes, we didn't change the connection timing, but the combination of: - Async message handling (fixed earlier) - Non-blocking channel sends (fixed earlier) - Early message arrival (fixed now) All exposed this timing issue that was always there but masked by synchronous blocking behavior. ## Testing ```bash go build docker-compose build docker-compose up -d docker-compose logs -f matterbridge ``` Send messages in Kosmi immediately after bot connects. They should all be queued and then flushed once the router is ready, with no messages dropped.