140 lines
4.1 KiB
Markdown
140 lines
4.1 KiB
Markdown
|
|
# CRITICAL FIX: Gateway Timing and Listener Start
|
||
|
|
|
||
|
|
## The Problem
|
||
|
|
|
||
|
|
Messages were being queued but NEVER flushed - the Remote channel was never becoming ready:
|
||
|
|
|
||
|
|
```
|
||
|
|
17:21:23 📦 Remote channel not ready, queued message (1 in queue)
|
||
|
|
17:21:23 📤 Attempting to flush 1 queued messages
|
||
|
|
17:21:23 📦 Flushed 0 messages, 1 still queued ← NEVER SENDS!
|
||
|
|
```
|
||
|
|
|
||
|
|
### Root Cause: Starting Listener Too Early
|
||
|
|
|
||
|
|
We were starting `listenForMessages()` in `Connect()`, but Matterbridge's architecture requires:
|
||
|
|
|
||
|
|
1. **`Connect()`** - Establish connection, set up client
|
||
|
|
2. **Router sets up gateway** - Creates the `b.Remote` channel and wires everything together
|
||
|
|
3. **`JoinChannel()`** - Called by router when gateway is READY
|
||
|
|
4. **THEN** start receiving messages
|
||
|
|
|
||
|
|
By starting the listener in `Connect()`, we were receiving messages BEFORE the gateway was ready, so `b.Remote` wasn't set up yet.
|
||
|
|
|
||
|
|
## The Solution
|
||
|
|
|
||
|
|
**Delay starting the message listener until `JoinChannel()` is called.**
|
||
|
|
|
||
|
|
### Changes Made
|
||
|
|
|
||
|
|
1. **In `graphql_ws_client.go`**:
|
||
|
|
- Removed `go c.listenForMessages()` from `Connect()`
|
||
|
|
- Added new method `StartListening()` that starts the listener
|
||
|
|
- Added to `KosmiClient` interface
|
||
|
|
|
||
|
|
2. **In `kosmi.go`**:
|
||
|
|
- Call `b.client.StartListening()` in `JoinChannel()`
|
||
|
|
- This is when the router has finished setting up the gateway
|
||
|
|
|
||
|
|
### Code Changes
|
||
|
|
|
||
|
|
```go
|
||
|
|
// graphql_ws_client.go
|
||
|
|
func (c *GraphQLWSClient) Connect() error {
|
||
|
|
// ... connection setup ...
|
||
|
|
|
||
|
|
c.log.Info("Native WebSocket client connected (listener will start when gateway is ready)")
|
||
|
|
|
||
|
|
// DON'T start listener here!
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *GraphQLWSClient) StartListening() {
|
||
|
|
c.log.Info("Starting message listener...")
|
||
|
|
go c.listenForMessages()
|
||
|
|
}
|
||
|
|
|
||
|
|
// kosmi.go
|
||
|
|
func (b *Bkosmi) JoinChannel(channel config.ChannelInfo) error {
|
||
|
|
b.Log.Infof("Channel %s is already connected via room URL", channel.Name)
|
||
|
|
|
||
|
|
// NOW start listening - the gateway is ready!
|
||
|
|
b.Log.Info("Gateway is ready, starting message listener...")
|
||
|
|
if b.client != nil {
|
||
|
|
b.client.StartListening()
|
||
|
|
}
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Why This Fixes Everything
|
||
|
|
|
||
|
|
### Before (Broken)
|
||
|
|
```
|
||
|
|
1. Connect() starts
|
||
|
|
2. listenForMessages() starts immediately
|
||
|
|
3. Messages start arriving
|
||
|
|
4. Try to send to b.Remote → NOT READY YET
|
||
|
|
5. Queue messages
|
||
|
|
6. Router finishes setup (b.Remote now ready)
|
||
|
|
7. Try to flush → but no new messages trigger flush
|
||
|
|
8. Messages stuck in queue forever
|
||
|
|
```
|
||
|
|
|
||
|
|
### After (Fixed)
|
||
|
|
```
|
||
|
|
1. Connect() starts
|
||
|
|
2. Connection established, but NO listener yet
|
||
|
|
3. Router finishes setup (b.Remote ready)
|
||
|
|
4. JoinChannel() called
|
||
|
|
5. StartListening() called
|
||
|
|
6. listenForMessages() starts NOW
|
||
|
|
7. Messages arrive
|
||
|
|
8. Send to b.Remote → SUCCESS!
|
||
|
|
9. No queue needed (but available as safety net)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Expected Behavior
|
||
|
|
|
||
|
|
### Logs Should Show
|
||
|
|
```
|
||
|
|
17:20:43 Starting bridge: kosmi.hyperspaceout
|
||
|
|
17:20:43 Connecting to Kosmi
|
||
|
|
17:21:00 Successfully connected to Kosmi
|
||
|
|
17:21:01 Native WebSocket client connected (listener will start when gateway is ready)
|
||
|
|
17:21:01 Successfully connected to Kosmi
|
||
|
|
17:21:01 kosmi.hyperspaceout: joining main
|
||
|
|
17:21:01 Gateway is ready, starting message listener...
|
||
|
|
17:21:01 Starting message listener...
|
||
|
|
17:21:01 🎧 [KOSMI WEBSOCKET] Message listener started
|
||
|
|
17:21:23 📨 [KOSMI WEBSOCKET] Received: type=next id=subscribe-messages
|
||
|
|
17:21:23 Received message from Kosmi: [2025-11-01T17:21:23-04:00] cottongin: IKR
|
||
|
|
17:21:23 ✅ Message forwarded to Matterbridge ← SUCCESS!
|
||
|
|
```
|
||
|
|
|
||
|
|
## Why This Matters
|
||
|
|
|
||
|
|
This is a **fundamental timing issue** in how bridges integrate with Matterbridge's gateway system. The gateway must be fully initialized before messages start flowing, otherwise the routing infrastructure isn't ready.
|
||
|
|
|
||
|
|
This pattern should be followed by ALL bridges:
|
||
|
|
- Connect and authenticate in `Connect()`
|
||
|
|
- Start receiving messages in `JoinChannel()` (or equivalent)
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
```bash
|
||
|
|
go build
|
||
|
|
docker-compose build
|
||
|
|
docker-compose up -d
|
||
|
|
docker-compose logs -f matterbridge
|
||
|
|
```
|
||
|
|
|
||
|
|
Send messages immediately after bot connects. They should:
|
||
|
|
1. NOT be queued
|
||
|
|
2. Be forwarded directly to IRC/other bridges
|
||
|
|
3. Appear in all connected channels
|
||
|
|
|
||
|
|
No more "Remote channel not ready" messages!
|
||
|
|
|