Skip to content

Commit f732d6a

Browse files
committed
Fix nil client context in AI carrier timing
1 parent 76497e8 commit f732d6a

2 files changed

Lines changed: 50 additions & 8 deletions

File tree

pkg/connector/client.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ func (dc *DummyClient) Disconnect() {
130130
dc.wg.Wait()
131131
}
132132

133+
func (dc *DummyClient) clientContext() context.Context {
134+
if dc != nil && dc.ctx != nil {
135+
return dc.ctx
136+
}
137+
return context.Background()
138+
}
139+
140+
func (dc *DummyClient) done() <-chan struct{} {
141+
return dc.clientContext().Done()
142+
}
143+
133144
func (dc *DummyClient) IsLoggedIn() bool {
134145
return true
135146
}
@@ -280,7 +291,7 @@ func (dc *DummyClient) HandleMatrixReaction(ctx context.Context, msg *bridgev2.M
280291
dc.wg.Add(1)
281292
go func() {
282293
defer dc.wg.Done()
283-
dc.queueAIApprovalResponse(dc.ctx, portal, target, response)
294+
dc.queueAIApprovalResponse(dc.clientContext(), portal, target, response)
284295
}()
285296

286297
logger := log.Info().
@@ -470,7 +481,7 @@ func (dc *DummyClient) queueRemoteEcho(msg *bridgev2.MatrixMessage, transactionI
470481
defer timer.Stop()
471482

472483
select {
473-
case <-dc.ctx.Done():
484+
case <-dc.done():
474485
return
475486
case <-timer.C:
476487
}
@@ -540,7 +551,7 @@ func (dc *DummyClient) queueAIResponse(ctx context.Context, portal *bridgev2.Por
540551
timer := time.NewTimer(delay)
541552
select {
542553
case <-timer.C:
543-
case <-dc.ctx.Done():
554+
case <-dc.done():
544555
timer.Stop()
545556
return
546557
}
@@ -696,7 +707,7 @@ func (dc *DummyClient) sleepUntilCarrierTime(run aistream.Run, carrier aistream.
696707
timer := time.NewTimer(delay)
697708
select {
698709
case <-timer.C:
699-
case <-dc.ctx.Done():
710+
case <-dc.done():
700711
timer.Stop()
701712
}
702713
}
@@ -769,10 +780,7 @@ func (dc *DummyClient) waitForMessageMXID(
769780
if dc == nil || dc.UserLogin == nil || dc.UserLogin.Bridge == nil || dc.UserLogin.Bridge.DB == nil || portal == nil {
770781
return ""
771782
}
772-
parent := dc.ctx
773-
if parent == nil {
774-
parent = context.Background()
775-
}
783+
parent := dc.clientContext()
776784
ctx, cancel := context.WithTimeout(parent, timeout)
777785
defer cancel()
778786

pkg/connector/client_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"testing"
55
"time"
66

7+
"github.com/beeper/ai-bridge/pkg/ag-ui"
8+
"github.com/beeper/ai-bridge/pkg/ai-stream"
79
"maunium.net/go/mautrix/event"
810
)
911

@@ -37,3 +39,35 @@ func TestGetRemoteEchoBehavior(t *testing.T) {
3739
})
3840
}
3941
}
42+
43+
func TestSleepUntilCarrierTimeWithoutConnectedContext(t *testing.T) {
44+
base := time.Now()
45+
run := aistream.Run{
46+
Events: []agui.Event{{
47+
"type": agui.EventRunStarted,
48+
"timestamp": base.UnixMilli(),
49+
"threadId": "thread-1",
50+
}},
51+
}
52+
carrier := aistream.Carrier{
53+
Envelopes: []aistream.Envelope{{
54+
Part: agui.Event{
55+
"type": agui.EventTextMessageContent,
56+
"timestamp": base.Add(time.Millisecond).UnixMilli(),
57+
"messageId": "message-1",
58+
},
59+
}},
60+
}
61+
62+
done := make(chan struct{})
63+
go func() {
64+
defer close(done)
65+
(&DummyClient{}).sleepUntilCarrierTime(run, carrier, base)
66+
}()
67+
68+
select {
69+
case <-done:
70+
case <-time.After(100 * time.Millisecond):
71+
t.Fatal("timed out waiting for carrier sleep without connected context")
72+
}
73+
}

0 commit comments

Comments
 (0)