Skip to content

Commit a84b0a7

Browse files
authored
Fix persistent connection request handling (#10)
1 parent 0a655ec commit a84b0a7

2 files changed

Lines changed: 101 additions & 58 deletions

File tree

persistent_stream.go

Lines changed: 54 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -45,67 +45,63 @@ func (d *Daemon) handlePersistentConn(r ggio.Reader, unsafeW ggio.WriteCloser) {
4545
return
4646
}
4747

48-
callID, err := uuid.FromBytes(req.CallId)
49-
if err != nil {
50-
log.Debugw("bad call id: ", "error", err)
51-
continue
48+
go d.handlePersistentConnRequest(req, w, &streamHandlers)
49+
}
50+
}
51+
52+
func (d *Daemon) handlePersistentConnRequest(req pb.PersistentConnectionRequest, w ggio.WriteCloser, streamHandlers *[]string) {
53+
callID, err := uuid.FromBytes(req.CallId)
54+
if err != nil {
55+
log.Debugw("bad call id: ", "error", err)
56+
return
57+
}
58+
59+
switch req.Message.(type) {
60+
case *pb.PersistentConnectionRequest_AddUnaryHandler:
61+
resp := d.doAddUnaryHandler(w, callID, req.GetAddUnaryHandler())
62+
63+
d.mx.Lock()
64+
if _, ok := resp.Message.(*pb.PersistentConnectionResponse_DaemonError); !ok {
65+
*streamHandlers = append(
66+
*streamHandlers,
67+
*req.GetAddUnaryHandler().Proto,
68+
)
5269
}
70+
d.mx.Unlock()
5371

54-
switch req.Message.(type) {
55-
case *pb.PersistentConnectionRequest_AddUnaryHandler:
56-
go func() {
57-
resp := d.doAddUnaryHandler(w, callID, req.GetAddUnaryHandler())
58-
59-
d.mx.Lock()
60-
if _, ok := resp.Message.(*pb.PersistentConnectionResponse_DaemonError); !ok {
61-
streamHandlers = append(
62-
streamHandlers,
63-
*req.GetAddUnaryHandler().Proto,
64-
)
65-
}
66-
d.mx.Unlock()
67-
68-
if err := w.WriteMsg(resp); err != nil {
69-
log.Debugw("error reading message", "error", err)
70-
return
71-
}
72-
}()
73-
74-
case *pb.PersistentConnectionRequest_CallUnary:
75-
go func() {
76-
ctx, cancel := context.WithCancel(context.Background())
77-
d.cancelUnary.Store(callID, cancel)
78-
defer cancel()
79-
80-
defer d.cancelUnary.Delete(callID)
81-
82-
resp := d.doUnaryCall(ctx, callID, &req)
83-
84-
if err := w.WriteMsg(resp); err != nil {
85-
log.Debugw("error reading message", "error", err)
86-
return
87-
}
88-
}()
89-
90-
case *pb.PersistentConnectionRequest_UnaryResponse:
91-
go func() {
92-
resp := d.sendReponseToRemote(&req)
93-
if err := w.WriteMsg(resp); err != nil {
94-
log.Debugw("error reading message", "error", err)
95-
return
96-
}
97-
}()
98-
99-
case *pb.PersistentConnectionRequest_Cancel:
100-
go func() {
101-
cf, found := d.cancelUnary.Load(callID)
102-
if !found {
103-
return
104-
}
105-
106-
cf.(context.CancelFunc)()
107-
}()
72+
if err := w.WriteMsg(resp); err != nil {
73+
log.Debugw("error reading message", "error", err)
74+
return
10875
}
76+
77+
case *pb.PersistentConnectionRequest_CallUnary:
78+
ctx, cancel := context.WithCancel(context.Background())
79+
d.cancelUnary.Store(callID, cancel)
80+
defer cancel()
81+
82+
defer d.cancelUnary.Delete(callID)
83+
84+
resp := d.doUnaryCall(ctx, callID, &req)
85+
86+
if err := w.WriteMsg(resp); err != nil {
87+
log.Debugw("error reading message", "error", err)
88+
return
89+
}
90+
91+
case *pb.PersistentConnectionRequest_UnaryResponse:
92+
resp := d.sendReponseToRemote(&req)
93+
if err := w.WriteMsg(resp); err != nil {
94+
log.Debugw("error reading message", "error", err)
95+
return
96+
}
97+
98+
case *pb.PersistentConnectionRequest_Cancel:
99+
cf, found := d.cancelUnary.Load(callID)
100+
if !found {
101+
return
102+
}
103+
104+
cf.(context.CancelFunc)()
109105
}
110106
}
111107

test/unary_handler_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,60 @@ import (
66
"errors"
77
"fmt"
88
"math"
9+
"sync"
910
"testing"
1011
"time"
1112

1213
"github.com/libp2p/go-libp2p-core/protocol"
1314
"github.com/libp2p/go-libp2p-daemon/p2pclient"
1415
)
1516

17+
func TestConcurrentCalls(t *testing.T) {
18+
_, p1, cancel1 := createDaemonClientPair(t)
19+
_, p2, cancel2 := createDaemonClientPair(t)
20+
21+
defer func() {
22+
cancel1()
23+
cancel2()
24+
}()
25+
26+
peer1ID, peer1Addrs, err := p1.Identify()
27+
if err != nil {
28+
t.Fatal(err)
29+
}
30+
if err := p2.Connect(peer1ID, peer1Addrs); err != nil {
31+
t.Fatal(err)
32+
}
33+
34+
var proto protocol.ID = "sqrt"
35+
if err := p1.AddUnaryHandler(proto, sqrtHandler); err != nil {
36+
t.Fatal(err)
37+
}
38+
39+
count := 100
40+
41+
var wg sync.WaitGroup
42+
var m sync.Map
43+
wg.Add(count)
44+
45+
for i := 0; i < count; i++ {
46+
go func(i int) {
47+
defer wg.Done()
48+
49+
reply, err := p2.CallUnaryHandler(context.Background(), peer1ID, proto, float64Bytes(float64(i)))
50+
if err != nil {
51+
panic(err)
52+
}
53+
54+
if _, loaded := m.LoadOrStore(float64FromBytes(reply), ""); loaded {
55+
panic(err)
56+
}
57+
}(i)
58+
}
59+
60+
wg.Wait()
61+
}
62+
1663
func TestUnaryCalls(t *testing.T) {
1764
_, p1, cancel1 := createDaemonClientPair(t)
1865
_, p2, cancel2 := createDaemonClientPair(t)

0 commit comments

Comments
 (0)