stream: register request, spawn session, send REQ on connect
This commit is contained in:
+66
-5
@@ -138,11 +138,31 @@ func NewRequestManager(e *Envoy) *RequestManager {
|
|||||||
func (m *RequestManager) Stream(
|
func (m *RequestManager) Stream(
|
||||||
filters [][]byte,
|
filters [][]byte,
|
||||||
) (string, <-chan ReqEvent, <-chan ReqClosed) {
|
) (string, <-chan ReqEvent, <-chan ReqClosed) {
|
||||||
// generate id
|
id := generateID()
|
||||||
// create channels
|
buffer := make(chan ReqEvent, 64)
|
||||||
// register request
|
events := make(chan ReqEvent)
|
||||||
// spawn session if connected
|
closed := make(chan ReqClosed, 1)
|
||||||
return "", nil, nil
|
|
||||||
|
req := &request{
|
||||||
|
id: id,
|
||||||
|
filters: filters,
|
||||||
|
buffer: buffer,
|
||||||
|
events: events,
|
||||||
|
closed: closed,
|
||||||
|
}
|
||||||
|
|
||||||
|
m.mu.Lock()
|
||||||
|
m.reqs[id] = req
|
||||||
|
go func() {
|
||||||
|
bufferedPipe(buffer, events)
|
||||||
|
close(events)
|
||||||
|
}()
|
||||||
|
if m.envoy.IsConnected() {
|
||||||
|
m.spawnSession(req)
|
||||||
|
}
|
||||||
|
m.mu.Unlock()
|
||||||
|
|
||||||
|
return id, events, closed
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RequestManager) Query(
|
func (m *RequestManager) Query(
|
||||||
@@ -162,6 +182,47 @@ func (m *RequestManager) Close() {
|
|||||||
m.wg.Wait()
|
m.wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *RequestManager) spawnSession(req *request) {
|
||||||
|
eose := make(chan struct{})
|
||||||
|
closed := make(chan struct{})
|
||||||
|
|
||||||
|
sub := &sessionSub{eose: eose, closed: closed}
|
||||||
|
m.inboxSubs[req.id] = sub
|
||||||
|
|
||||||
|
var once sync.Once
|
||||||
|
terminate := func(r terminateReason) {
|
||||||
|
once.Do(func() {
|
||||||
|
m.mu.Lock()
|
||||||
|
close(eose)
|
||||||
|
close(closed)
|
||||||
|
delete(m.inboxSubs, req.id)
|
||||||
|
delete(m.sessions, req.id)
|
||||||
|
m.mu.Unlock()
|
||||||
|
m.sessionWg.Done()
|
||||||
|
if r == termReceivedClosed {
|
||||||
|
req.once.Do(func() {
|
||||||
|
close(req.buffer)
|
||||||
|
close(req.closed)
|
||||||
|
})
|
||||||
|
m.mu.Lock()
|
||||||
|
delete(m.reqs, req.id)
|
||||||
|
m.mu.Unlock()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
req_env := envelope.EncloseReq(req.id, req.filters)
|
||||||
|
sess := newSession(
|
||||||
|
m.ctx, req.id, req_env,
|
||||||
|
eose, closed, m.done,
|
||||||
|
m.envoy.Send, terminate,
|
||||||
|
false, m.handler,
|
||||||
|
)
|
||||||
|
m.sessions[req.id] = sess
|
||||||
|
m.sessionWg.Add(1)
|
||||||
|
go sess.run()
|
||||||
|
}
|
||||||
|
|
||||||
func (m *RequestManager) start() {
|
func (m *RequestManager) start() {
|
||||||
// start all request sessions
|
// start all request sessions
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-4
@@ -208,10 +208,34 @@ func TestRequestManager_Session(t *testing.T) {
|
|||||||
|
|
||||||
func TestRequestManager_Stream(t *testing.T) {
|
func TestRequestManager_Stream(t *testing.T) {
|
||||||
t.Run("spawns session and sends req when connected", func(t *testing.T) {
|
t.Run("spawns session and sends req when connected", func(t *testing.T) {
|
||||||
// connect the envoy before calling Stream
|
p := newMockPool(t)
|
||||||
// call Stream with filters
|
emb := NewEmbassy(p.ctx, p.plugin, nil)
|
||||||
// assert the mock send was called with a REQ envelope
|
err := emb.Dispatch(p.url)
|
||||||
// assert the generated id appears in the REQ envelope
|
assert.NoError(t, err)
|
||||||
|
envoy := emb.Call(p.url)
|
||||||
|
|
||||||
|
p.connect()
|
||||||
|
Eventually(t, envoy.IsConnected, "envoy should be connected")
|
||||||
|
|
||||||
|
m := NewRequestManager(envoy)
|
||||||
|
filters := [][]byte{[]byte(`{}`)}
|
||||||
|
id, events, closed := m.Stream(filters)
|
||||||
|
|
||||||
|
assert.NotEmpty(t, id)
|
||||||
|
assert.NotNil(t, events)
|
||||||
|
assert.NotNil(t, closed)
|
||||||
|
|
||||||
|
var got []byte
|
||||||
|
Eventually(t, func() bool {
|
||||||
|
select {
|
||||||
|
case got = <-p.sent:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}, "expected REQ send")
|
||||||
|
|
||||||
|
assert.Equal(t, []byte(envelope.EncloseReq(id, filters)), got)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("registers but does not spawn session when disconnected", func(t *testing.T) {
|
t.Run("registers but does not spawn session when disconnected", func(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user