# Critical Fix: Asynchronous Message Handling

## The Problem

The bot was only receiving ONE message from Kosmi then hanging, even though the WebSocket stayed connected.

### Root Cause

We were reading WebSocket responses **synchronously** during connection setup, but the server sends responses in a different order than we were expecting:

**What we were doing:**
1. Send `ExtendedCurrentUserQuery` → Try to read response immediately
2. Send `RoomChatQuery` → Try to read response immediately  
3. Send `JoinRoom` → Try to read response immediately (loop 10 times)

**What the server actually sends:**
1. `complete` for `current-user` (from ExtendedCurrentUserQuery)
2. `next` for `join-room` (from JoinRoom)
3. `next` for `room-chat-query` (from RoomChatQuery)
4. ... more responses ...

**The mismatch:**
- We sent `RoomChatQuery` and tried to read its response
- But we actually read the `complete` message from the previous `current-user` query!
- This consumed a message that `listenForMessages` should have handled
- The message loop got out of sync and stopped processing new messages

### Evidence from Logs

```
time="2025-11-01T16:36:06-04:00" level=info msg="Chat history response: type=complete id=current-user"
```

We sent a query with ID `room-chat-query` but received a response with ID `current-user` - wrong message!

## The Fix

**Stop reading responses synchronously during setup.** Let the `listenForMessages` goroutine handle ALL incoming messages.

### Changes Made

1. **Removed synchronous read after `ExtendedCurrentUserQuery`**
   - Before: Send query → Read response
   - After: Send query → Continue (let listenForMessages handle it)

2. **Removed synchronous read after `RoomChatQuery`**
   - Before: Send query → Read response
   - After: Send query → Continue (let listenForMessages handle it)

3. **Removed synchronous loop after `JoinRoom`**
   - Before: Send mutation → Loop 10 times reading responses
   - After: Send mutation → Brief sleep → Continue (let listenForMessages handle it)

4. **Enhanced `listenForMessages` to handle all message types**
   - Added switch statement for `messageTypeNext`, `messageTypeError`, `messageTypeComplete`
   - Added specific handling for known operation IDs (`current-user`, `room-chat-query`, `join-room`, `subscribe-messages`)
   - Added better logging for debugging

### New Message Flow

```
Connection Setup (synchronous):
├─ Send connection_init
├─ Wait for connection_ack (ONLY synchronous read)
├─ Send ExtendedCurrentUserQuery
├─ Send JoinRoom
├─ Send RoomChatQuery
├─ Send RoomDisconnect subscription
├─ Send MemberJoins subscription
├─ Send MemberLeaves subscription
├─ Send NewMessageSubscription
└─ Start listenForMessages goroutine

listenForMessages (asynchronous):
├─ Reads ALL incoming messages
├─ Handles responses for all queries/mutations/subscriptions
└─ Processes new chat messages
```

## Expected Behavior After Fix

1. ✅ Bot connects and authenticates
2. ✅ Bot sends all setup queries/subscriptions
3. ✅ `listenForMessages` handles all responses in order
4. ✅ Bot receives ALL messages continuously (not just one)
5. ✅ No "ALREADY_CONNECTED" errors
6. ✅ WebSocket stays alive and processes messages

## Testing

```bash
go build
docker-compose build
docker-compose up -d
docker-compose logs -f matterbridge
```

Look for:
- `🎧 [KOSMI WEBSOCKET] Message listener started`
- `📨 [KOSMI WEBSOCKET] Received: type=next id=current-user`
- `✅ Received current user data`
- `📨 [KOSMI WEBSOCKET] Received: type=next id=join-room`
- `✅ Successfully joined room`
- `📨 [KOSMI WEBSOCKET] Received: type=next id=room-chat-query`
- `✅ Received chat history`
- Multiple `📨 [KOSMI WEBSOCKET] Received: type=next id=subscribe-messages`
- Multiple `Received message from Kosmi:` entries

## Why This Matters

GraphQL-WS is an **asynchronous protocol**. The server can send responses in any order, and multiple responses can be in flight at once. By trying to read responses synchronously, we were:

1. **Breaking the message order** - Reading messages meant for the listener
2. **Creating race conditions** - Setup code and listener competing for messages
3. **Blocking the connection** - Waiting for specific responses that might never come (or come in different order)

The fix ensures that **only one goroutine** (`listenForMessages`) reads from the WebSocket, eliminating all race conditions and ensuring messages are processed in the order they arrive.

