starpc 0.33.1 → 0.33.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/srpc/client-rpc.go +31 -26
- package/srpc/common-rpc.go +74 -67
- package/srpc/server-rpc.go +25 -19
package/package.json
CHANGED
package/srpc/client-rpc.go
CHANGED
|
@@ -32,21 +32,26 @@ func (r *ClientRPC) Start(writer PacketWriter, writeFirstMsg bool, firstMsg []by
|
|
|
32
32
|
return context.Canceled
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
r.mtx.Lock()
|
|
36
|
-
defer r.mtx.Unlock()
|
|
37
|
-
defer r.bcast.Broadcast()
|
|
38
|
-
r.writer = writer
|
|
39
35
|
var firstMsgEmpty bool
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
36
|
+
var err error
|
|
37
|
+
r.bcast.HoldLock(func(broadcast func(), getWaitCh func() <-chan struct{}) {
|
|
38
|
+
r.writer = writer
|
|
39
|
+
|
|
40
|
+
if writeFirstMsg {
|
|
41
|
+
firstMsgEmpty = len(firstMsg) == 0
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
pkt := NewCallStartPacket(r.service, r.method, firstMsg, firstMsgEmpty)
|
|
45
|
+
err = writer.WritePacket(pkt)
|
|
46
|
+
if err != nil {
|
|
47
|
+
r.ctxCancel()
|
|
48
|
+
_ = writer.Close()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
broadcast()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
return err
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
// HandlePacketData handles an incoming unparsed message packet.
|
|
@@ -60,14 +65,14 @@ func (r *ClientRPC) HandlePacketData(data []byte) error {
|
|
|
60
65
|
|
|
61
66
|
// HandleStreamClose handles the stream closing optionally w/ an error.
|
|
62
67
|
func (r *ClientRPC) HandleStreamClose(closeErr error) {
|
|
63
|
-
r.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
r.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
r.bcast.HoldLock(func(broadcast func(), getWaitCh func() <-chan struct{}) {
|
|
69
|
+
if closeErr != nil && r.remoteErr == nil {
|
|
70
|
+
r.remoteErr = closeErr
|
|
71
|
+
}
|
|
72
|
+
r.dataClosed = true
|
|
73
|
+
r.ctxCancel()
|
|
74
|
+
broadcast()
|
|
75
|
+
})
|
|
71
76
|
}
|
|
72
77
|
|
|
73
78
|
// HandlePacket handles an incoming parsed message packet.
|
|
@@ -102,8 +107,8 @@ func (r *ClientRPC) Close() {
|
|
|
102
107
|
if r.writer != nil {
|
|
103
108
|
_ = r.WriteCancel()
|
|
104
109
|
}
|
|
105
|
-
|
|
106
|
-
r.
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
|
|
111
|
+
r.bcast.HoldLock(func(broadcast func(), getWaitCh func() <-chan struct{}) {
|
|
112
|
+
r.closeLocked(broadcast)
|
|
113
|
+
})
|
|
109
114
|
}
|
package/srpc/common-rpc.go
CHANGED
|
@@ -3,7 +3,6 @@ package srpc
|
|
|
3
3
|
import (
|
|
4
4
|
"context"
|
|
5
5
|
"io"
|
|
6
|
-
"sync"
|
|
7
6
|
|
|
8
7
|
"github.com/aperturerobotics/util/broadcast"
|
|
9
8
|
"github.com/pkg/errors"
|
|
@@ -19,9 +18,7 @@ type commonRPC struct {
|
|
|
19
18
|
service string
|
|
20
19
|
// method is the rpc method
|
|
21
20
|
method string
|
|
22
|
-
//
|
|
23
|
-
mtx sync.Mutex
|
|
24
|
-
// bcast broadcasts when below fields change
|
|
21
|
+
// bcast guards below fields
|
|
25
22
|
bcast broadcast.Broadcast
|
|
26
23
|
// writer is the writer to write messages to
|
|
27
24
|
writer PacketWriter
|
|
@@ -45,21 +42,25 @@ func (c *commonRPC) Context() context.Context {
|
|
|
45
42
|
return c.ctx
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
// Wait waits for the RPC to finish.
|
|
45
|
+
// Wait waits for the RPC to finish (remote end closed the stream).
|
|
49
46
|
func (c *commonRPC) Wait(ctx context.Context) error {
|
|
50
47
|
for {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
var dataClosed bool
|
|
49
|
+
var err error
|
|
50
|
+
var waitCh <-chan struct{}
|
|
51
|
+
c.bcast.HoldLock(func(broadcast func(), getWaitCh func() <-chan struct{}) {
|
|
52
|
+
dataClosed, err = c.dataClosed, c.remoteErr
|
|
53
|
+
waitCh = getWaitCh()
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
if dataClosed {
|
|
55
57
|
return err
|
|
56
58
|
}
|
|
57
|
-
|
|
58
|
-
c.mtx.Unlock()
|
|
59
|
+
|
|
59
60
|
select {
|
|
60
61
|
case <-ctx.Done():
|
|
61
62
|
return context.Canceled
|
|
62
|
-
case <-
|
|
63
|
+
case <-waitCh:
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
}
|
|
@@ -68,39 +69,43 @@ func (c *commonRPC) Wait(ctx context.Context) error {
|
|
|
68
69
|
//
|
|
69
70
|
// returns io.EOF if the stream ended without a packet.
|
|
70
71
|
func (c *commonRPC) ReadOne() ([]byte, error) {
|
|
72
|
+
var hasMsg bool
|
|
71
73
|
var msg []byte
|
|
72
74
|
var err error
|
|
73
75
|
var ctxDone bool
|
|
74
76
|
for {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return nil, err
|
|
83
|
-
}
|
|
84
|
-
if len(c.dataQueue) != 0 {
|
|
85
|
-
msg = c.dataQueue[0]
|
|
86
|
-
c.dataQueue[0] = nil
|
|
87
|
-
c.dataQueue = c.dataQueue[1:]
|
|
88
|
-
c.mtx.Unlock()
|
|
89
|
-
return msg, nil
|
|
90
|
-
}
|
|
91
|
-
if c.dataClosed || c.remoteErr != nil {
|
|
92
|
-
err = c.remoteErr
|
|
93
|
-
if err == nil {
|
|
94
|
-
err = io.EOF
|
|
77
|
+
var waitCh <-chan struct{}
|
|
78
|
+
c.bcast.HoldLock(func(broadcast func(), getWaitCh func() <-chan struct{}) {
|
|
79
|
+
if ctxDone && !c.dataClosed {
|
|
80
|
+
// context must have been canceled locally
|
|
81
|
+
c.closeLocked(broadcast)
|
|
82
|
+
err = context.Canceled
|
|
83
|
+
return
|
|
95
84
|
}
|
|
96
|
-
|
|
97
|
-
|
|
85
|
+
|
|
86
|
+
if len(c.dataQueue) != 0 {
|
|
87
|
+
msg = c.dataQueue[0]
|
|
88
|
+
hasMsg = true
|
|
89
|
+
c.dataQueue[0] = nil
|
|
90
|
+
c.dataQueue = c.dataQueue[1:]
|
|
91
|
+
} else if c.dataClosed || c.remoteErr != nil {
|
|
92
|
+
err = c.remoteErr
|
|
93
|
+
if err == nil {
|
|
94
|
+
err = io.EOF
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
waitCh = getWaitCh()
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
if hasMsg || err != nil {
|
|
102
|
+
return msg, err
|
|
98
103
|
}
|
|
99
|
-
|
|
104
|
+
|
|
100
105
|
select {
|
|
101
106
|
case <-c.ctx.Done():
|
|
102
107
|
ctxDone = true
|
|
103
|
-
case <-
|
|
108
|
+
case <-waitCh:
|
|
104
109
|
}
|
|
105
110
|
}
|
|
106
111
|
}
|
|
@@ -116,17 +121,17 @@ func (c *commonRPC) WriteCallData(data []byte, complete bool, err error) error {
|
|
|
116
121
|
|
|
117
122
|
// HandleStreamClose handles the incoming stream closing w/ optional error.
|
|
118
123
|
func (c *commonRPC) HandleStreamClose(closeErr error) {
|
|
119
|
-
c.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
124
|
+
c.bcast.HoldLock(func(broadcast func(), getWaitCh func() <-chan struct{}) {
|
|
125
|
+
if closeErr != nil && c.remoteErr == nil {
|
|
126
|
+
c.remoteErr = closeErr
|
|
127
|
+
}
|
|
128
|
+
c.dataClosed = true
|
|
129
|
+
c.ctxCancel()
|
|
130
|
+
if c.writer != nil {
|
|
131
|
+
_ = c.writer.Close()
|
|
132
|
+
}
|
|
133
|
+
broadcast()
|
|
134
|
+
})
|
|
130
135
|
}
|
|
131
136
|
|
|
132
137
|
// HandleCallCancel handles the call cancel packet.
|
|
@@ -137,29 +142,31 @@ func (c *commonRPC) HandleCallCancel() error {
|
|
|
137
142
|
|
|
138
143
|
// HandleCallData handles the call data packet.
|
|
139
144
|
func (c *commonRPC) HandleCallData(pkt *CallData) error {
|
|
140
|
-
|
|
141
|
-
|
|
145
|
+
var err error
|
|
146
|
+
c.bcast.HoldLock(func(broadcast func(), getWaitCh func() <-chan struct{}) {
|
|
147
|
+
if c.dataClosed {
|
|
148
|
+
err = ErrCompleted
|
|
149
|
+
return
|
|
150
|
+
}
|
|
142
151
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
if data := pkt.GetData(); len(data) != 0 || pkt.GetDataIsZero() {
|
|
153
|
+
c.dataQueue = append(c.dataQueue, data)
|
|
154
|
+
}
|
|
146
155
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
156
|
+
complete := pkt.GetComplete()
|
|
157
|
+
if err := pkt.GetError(); len(err) != 0 {
|
|
158
|
+
complete = true
|
|
159
|
+
c.remoteErr = errors.New(err)
|
|
160
|
+
}
|
|
150
161
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
c.remoteErr = errors.New(err)
|
|
155
|
-
}
|
|
162
|
+
if complete {
|
|
163
|
+
c.dataClosed = true
|
|
164
|
+
}
|
|
156
165
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
166
|
+
broadcast()
|
|
167
|
+
})
|
|
160
168
|
|
|
161
|
-
|
|
162
|
-
return nil
|
|
169
|
+
return err
|
|
163
170
|
}
|
|
164
171
|
|
|
165
172
|
// WriteCancel writes a call cancel packet.
|
|
@@ -171,7 +178,7 @@ func (c *commonRPC) WriteCancel() error {
|
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
// closeLocked releases resources held by the RPC.
|
|
174
|
-
func (c *commonRPC) closeLocked() {
|
|
181
|
+
func (c *commonRPC) closeLocked(broadcast func()) {
|
|
175
182
|
c.dataClosed = true
|
|
176
183
|
if c.remoteErr == nil {
|
|
177
184
|
c.remoteErr = context.Canceled
|
|
@@ -179,6 +186,6 @@ func (c *commonRPC) closeLocked() {
|
|
|
179
186
|
if c.writer != nil {
|
|
180
187
|
_ = c.writer.Close()
|
|
181
188
|
}
|
|
182
|
-
|
|
189
|
+
broadcast()
|
|
183
190
|
c.ctxCancel()
|
|
184
191
|
}
|
package/srpc/server-rpc.go
CHANGED
|
@@ -57,27 +57,33 @@ func (r *ServerRPC) HandlePacket(msg *Packet) error {
|
|
|
57
57
|
|
|
58
58
|
// HandleCallStart handles the call start packet.
|
|
59
59
|
func (r *ServerRPC) HandleCallStart(pkt *CallStart) error {
|
|
60
|
-
|
|
61
|
-
defer r.mtx.Unlock()
|
|
62
|
-
// process start: method and service
|
|
63
|
-
if r.method != "" || r.service != "" {
|
|
64
|
-
return errors.New("call start must be sent only once")
|
|
65
|
-
}
|
|
66
|
-
if r.dataClosed {
|
|
67
|
-
return ErrCompleted
|
|
68
|
-
}
|
|
69
|
-
service, method := pkt.GetRpcService(), pkt.GetRpcMethod()
|
|
70
|
-
r.service, r.method = service, method
|
|
60
|
+
var err error
|
|
71
61
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
r.
|
|
75
|
-
|
|
62
|
+
r.bcast.HoldLock(func(broadcast func(), getWaitCh func() <-chan struct{}) {
|
|
63
|
+
// process start: method and service
|
|
64
|
+
if r.method != "" || r.service != "" {
|
|
65
|
+
err = errors.New("call start must be sent only once")
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
if r.dataClosed {
|
|
69
|
+
err = ErrCompleted
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
service, method := pkt.GetRpcService(), pkt.GetRpcMethod()
|
|
74
|
+
r.service, r.method = service, method
|
|
75
|
+
|
|
76
|
+
// process first data packet, if included
|
|
77
|
+
if data := pkt.GetData(); len(data) != 0 || pkt.GetDataIsZero() {
|
|
78
|
+
r.dataQueue = append(r.dataQueue, data)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// invoke the rpc
|
|
82
|
+
broadcast()
|
|
83
|
+
go r.invokeRPC(service, method)
|
|
84
|
+
})
|
|
76
85
|
|
|
77
|
-
|
|
78
|
-
r.bcast.Broadcast()
|
|
79
|
-
go r.invokeRPC(service, method)
|
|
80
|
-
return nil
|
|
86
|
+
return err
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
// invokeRPC invokes the RPC after CallStart is received.
|