Live: experimental HA with Redis (#34851)

This commit is contained in:
Alexander Emelin
2021-06-24 11:07:09 +03:00
committed by GitHub
parent 437faa72a9
commit 98893c0420
20 changed files with 785 additions and 308 deletions
+15 -14
View File
@@ -18,18 +18,19 @@ var (
logger = log.New("live.runstream")
)
//go:generate mockgen -destination=mock.go -package=runstream github.com/grafana/grafana/pkg/services/live/runstream ChannelSender,PresenceGetter,StreamRunner,PluginContextGetter
//go:generate mockgen -destination=mock.go -package=runstream github.com/grafana/grafana/pkg/services/live/runstream ChannelLocalPublisher,NumLocalSubscribersGetter,StreamRunner,PluginContextGetter
type ChannelSender interface {
Send(channel string, data []byte) error
type ChannelLocalPublisher interface {
PublishLocal(channel string, data []byte) error
}
type PluginContextGetter interface {
GetPluginContext(user *models.SignedInUser, pluginID string, datasourceUID string, skipCache bool) (backend.PluginContext, bool, error)
}
type PresenceGetter interface {
GetNumSubscribers(channel string) (int, error)
type NumLocalSubscribersGetter interface {
// GetNumSubscribers returns number of channel subscribers throughout all nodes.
GetNumLocalSubscribers(channel string) (int, error)
}
type StreamRunner interface {
@@ -37,12 +38,12 @@ type StreamRunner interface {
}
type packetSender struct {
channelSender ChannelSender
channel string
channelLocalPublisher ChannelLocalPublisher
channel string
}
func (p *packetSender) Send(packet *backend.StreamPacket) error {
return p.channelSender.Send(p.channel, packet.Data)
return p.channelLocalPublisher.PublishLocal(p.channel, packet.Data)
}
// Manager manages streams from Grafana to plugins (i.e. RunStream method).
@@ -51,9 +52,9 @@ type Manager struct {
baseCtx context.Context
streams map[string]streamContext
datasourceStreams map[string]map[string]struct{}
presenceGetter PresenceGetter
presenceGetter NumLocalSubscribersGetter
pluginContextGetter PluginContextGetter
channelSender ChannelSender
channelSender ChannelLocalPublisher
registerCh chan submitRequest
closedCh chan struct{}
checkInterval time.Duration
@@ -79,7 +80,7 @@ const (
)
// NewManager creates new Manager.
func NewManager(channelSender ChannelSender, presenceGetter PresenceGetter, pluginContextGetter PluginContextGetter, opts ...ManagerOption) *Manager {
func NewManager(channelSender ChannelLocalPublisher, presenceGetter NumLocalSubscribersGetter, pluginContextGetter PluginContextGetter, opts ...ManagerOption) *Manager {
sm := &Manager{
streams: make(map[string]streamContext),
datasourceStreams: map[string]map[string]struct{}{},
@@ -201,9 +202,9 @@ func (s *Manager) watchStream(ctx context.Context, cancelFn func(), sr streamReq
}
}
case <-presenceTicker.C:
numSubscribers, err := s.presenceGetter.GetNumSubscribers(sr.Channel)
numSubscribers, err := s.presenceGetter.GetNumLocalSubscribers(sr.Channel)
if err != nil {
logger.Error("Error checking num subscribers", "channel", sr.Channel, "path", sr.Path)
logger.Error("Error checking num subscribers", "channel", sr.Channel, "path", sr.Path, "error", err)
continue
}
if numSubscribers > 0 {
@@ -301,7 +302,7 @@ func (s *Manager) runStream(ctx context.Context, cancelFn func(), sr streamReque
PluginContext: pluginCtx,
Path: sr.Path,
},
backend.NewStreamSender(&packetSender{channelSender: s.channelSender, channel: sr.Channel}),
backend.NewStreamSender(&packetSender{channelLocalPublisher: s.channelSender, channel: sr.Channel}),
)
if err != nil {
if errors.Is(ctx.Err(), context.Canceled) {
+28 -28
View File
@@ -27,11 +27,11 @@ func TestStreamManager_Run(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockChannelSender := NewMockChannelSender(mockCtrl)
mockPresenceGetter := NewMockPresenceGetter(mockCtrl)
mockChannelPublisher := NewMockChannelLocalPublisher(mockCtrl)
mockNumSubscribersGetter := NewMockNumLocalSubscribersGetter(mockCtrl)
mockContextGetter := NewMockPluginContextGetter(mockCtrl)
manager := NewManager(mockChannelSender, mockPresenceGetter, mockContextGetter)
manager := NewManager(mockChannelPublisher, mockNumSubscribersGetter, mockContextGetter)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -48,11 +48,11 @@ func TestStreamManager_SubmitStream_Send(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockPacketSender := NewMockChannelSender(mockCtrl)
mockPresenceGetter := NewMockPresenceGetter(mockCtrl)
mockPacketSender := NewMockChannelLocalPublisher(mockCtrl)
mockNumSubscribersGetter := NewMockNumLocalSubscribersGetter(mockCtrl)
mockContextGetter := NewMockPluginContextGetter(mockCtrl)
manager := NewManager(mockPacketSender, mockPresenceGetter, mockContextGetter)
manager := NewManager(mockPacketSender, mockNumSubscribersGetter, mockContextGetter)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -79,7 +79,7 @@ func TestStreamManager_SubmitStream_Send(t *testing.T) {
return testPluginContext, true, nil
}).Times(0)
mockPacketSender.EXPECT().Send("1/test", gomock.Any()).Times(1)
mockPacketSender.EXPECT().PublishLocal("1/test", gomock.Any()).Times(1)
mockStreamRunner := NewMockStreamRunner(mockCtrl)
mockStreamRunner.EXPECT().RunStream(
@@ -113,11 +113,11 @@ func TestStreamManager_SubmitStream_DifferentOrgID(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockPacketSender := NewMockChannelSender(mockCtrl)
mockPresenceGetter := NewMockPresenceGetter(mockCtrl)
mockPacketSender := NewMockChannelLocalPublisher(mockCtrl)
mockNumSubscribersGetter := NewMockNumLocalSubscribersGetter(mockCtrl)
mockContextGetter := NewMockPluginContextGetter(mockCtrl)
manager := NewManager(mockPacketSender, mockPresenceGetter, mockContextGetter)
manager := NewManager(mockPacketSender, mockNumSubscribersGetter, mockContextGetter)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -130,8 +130,8 @@ func TestStreamManager_SubmitStream_DifferentOrgID(t *testing.T) {
doneCh1 := make(chan struct{})
doneCh2 := make(chan struct{})
mockPacketSender.EXPECT().Send("1/test", gomock.Any()).Times(1)
mockPacketSender.EXPECT().Send("2/test", gomock.Any()).Times(1)
mockPacketSender.EXPECT().PublishLocal("1/test", gomock.Any()).Times(1)
mockPacketSender.EXPECT().PublishLocal("2/test", gomock.Any()).Times(1)
mockContextGetter.EXPECT().GetPluginContext(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(user *models.SignedInUser, pluginID string, datasourceUID string, skipCache bool) (backend.PluginContext, bool, error) {
return backend.PluginContext{}, true, nil
@@ -184,14 +184,14 @@ func TestStreamManager_SubmitStream_CloseNoSubscribers(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockPacketSender := NewMockChannelSender(mockCtrl)
mockPresenceGetter := NewMockPresenceGetter(mockCtrl)
mockPacketSender := NewMockChannelLocalPublisher(mockCtrl)
mockNumSubscribersGetter := NewMockNumLocalSubscribersGetter(mockCtrl)
mockContextGetter := NewMockPluginContextGetter(mockCtrl)
// Create manager with very fast num subscribers checks.
manager := NewManager(
mockPacketSender,
mockPresenceGetter,
mockNumSubscribersGetter,
mockContextGetter,
WithCheckConfig(10*time.Millisecond, 3),
)
@@ -209,7 +209,7 @@ func TestStreamManager_SubmitStream_CloseNoSubscribers(t *testing.T) {
return backend.PluginContext{}, true, nil
}).Times(0)
mockPresenceGetter.EXPECT().GetNumSubscribers("1/test").Return(0, nil).Times(3)
mockNumSubscribersGetter.EXPECT().GetNumLocalSubscribers("1/test").Return(0, nil).Times(3)
mockStreamRunner := NewMockStreamRunner(mockCtrl)
mockStreamRunner.EXPECT().RunStream(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
@@ -231,11 +231,11 @@ func TestStreamManager_SubmitStream_ErrorRestartsRunStream(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockPacketSender := NewMockChannelSender(mockCtrl)
mockPresenceGetter := NewMockPresenceGetter(mockCtrl)
mockPacketSender := NewMockChannelLocalPublisher(mockCtrl)
mockNumSubscribersGetter := NewMockNumLocalSubscribersGetter(mockCtrl)
mockContextGetter := NewMockPluginContextGetter(mockCtrl)
manager := NewManager(mockPacketSender, mockPresenceGetter, mockContextGetter)
manager := NewManager(mockPacketSender, mockNumSubscribersGetter, mockContextGetter)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -284,11 +284,11 @@ func TestStreamManager_SubmitStream_NilErrorStopsRunStream(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockPacketSender := NewMockChannelSender(mockCtrl)
mockPresenceGetter := NewMockPresenceGetter(mockCtrl)
mockPacketSender := NewMockChannelLocalPublisher(mockCtrl)
mockNumSubscribersGetter := NewMockNumLocalSubscribersGetter(mockCtrl)
mockContextGetter := NewMockPluginContextGetter(mockCtrl)
manager := NewManager(mockPacketSender, mockPresenceGetter, mockContextGetter)
manager := NewManager(mockPacketSender, mockNumSubscribersGetter, mockContextGetter)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -317,11 +317,11 @@ func TestStreamManager_HandleDatasourceUpdate(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockPacketSender := NewMockChannelSender(mockCtrl)
mockPresenceGetter := NewMockPresenceGetter(mockCtrl)
mockPacketSender := NewMockChannelLocalPublisher(mockCtrl)
mockNumSubscribersGetter := NewMockNumLocalSubscribersGetter(mockCtrl)
mockContextGetter := NewMockPluginContextGetter(mockCtrl)
manager := NewManager(mockPacketSender, mockPresenceGetter, mockContextGetter)
manager := NewManager(mockPacketSender, mockNumSubscribersGetter, mockContextGetter)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -383,11 +383,11 @@ func TestStreamManager_HandleDatasourceDelete(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockPacketSender := NewMockChannelSender(mockCtrl)
mockPresenceGetter := NewMockPresenceGetter(mockCtrl)
mockPacketSender := NewMockChannelLocalPublisher(mockCtrl)
mockNumSubscribersGetter := NewMockNumLocalSubscribersGetter(mockCtrl)
mockContextGetter := NewMockPluginContextGetter(mockCtrl)
manager := NewManager(mockPacketSender, mockPresenceGetter, mockContextGetter)
manager := NewManager(mockPacketSender, mockNumSubscribersGetter, mockContextGetter)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
+35 -35
View File
@@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/grafana/grafana/pkg/services/live/runstream (interfaces: ChannelSender,PresenceGetter,StreamRunner,PluginContextGetter)
// Source: github.com/grafana/grafana/pkg/services/live/runstream (interfaces: ChannelLocalPublisher,NumLocalSubscribersGetter,StreamRunner,PluginContextGetter)
// Package runstream is a generated GoMock package.
package runstream
@@ -13,79 +13,79 @@ import (
models "github.com/grafana/grafana/pkg/models"
)
// MockChannelSender is a mock of ChannelSender interface.
type MockChannelSender struct {
// MockChannelLocalPublisher is a mock of ChannelLocalPublisher interface.
type MockChannelLocalPublisher struct {
ctrl *gomock.Controller
recorder *MockChannelSenderMockRecorder
recorder *MockChannelLocalPublisherMockRecorder
}
// MockChannelSenderMockRecorder is the mock recorder for MockChannelSender.
type MockChannelSenderMockRecorder struct {
mock *MockChannelSender
// MockChannelLocalPublisherMockRecorder is the mock recorder for MockChannelLocalPublisher.
type MockChannelLocalPublisherMockRecorder struct {
mock *MockChannelLocalPublisher
}
// NewMockChannelSender creates a new mock instance.
func NewMockChannelSender(ctrl *gomock.Controller) *MockChannelSender {
mock := &MockChannelSender{ctrl: ctrl}
mock.recorder = &MockChannelSenderMockRecorder{mock}
// NewMockChannelLocalPublisher creates a new mock instance.
func NewMockChannelLocalPublisher(ctrl *gomock.Controller) *MockChannelLocalPublisher {
mock := &MockChannelLocalPublisher{ctrl: ctrl}
mock.recorder = &MockChannelLocalPublisherMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockChannelSender) EXPECT() *MockChannelSenderMockRecorder {
func (m *MockChannelLocalPublisher) EXPECT() *MockChannelLocalPublisherMockRecorder {
return m.recorder
}
// Send mocks base method.
func (m *MockChannelSender) Send(arg0 string, arg1 []byte) error {
// PublishLocal mocks base method.
func (m *MockChannelLocalPublisher) PublishLocal(arg0 string, arg1 []byte) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Send", arg0, arg1)
ret := m.ctrl.Call(m, "PublishLocal", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// Send indicates an expected call of Send.
func (mr *MockChannelSenderMockRecorder) Send(arg0, arg1 interface{}) *gomock.Call {
// PublishLocal indicates an expected call of PublishLocal.
func (mr *MockChannelLocalPublisherMockRecorder) PublishLocal(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Send", reflect.TypeOf((*MockChannelSender)(nil).Send), arg0, arg1)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishLocal", reflect.TypeOf((*MockChannelLocalPublisher)(nil).PublishLocal), arg0, arg1)
}
// MockPresenceGetter is a mock of PresenceGetter interface.
type MockPresenceGetter struct {
// MockNumLocalSubscribersGetter is a mock of NumLocalSubscribersGetter interface.
type MockNumLocalSubscribersGetter struct {
ctrl *gomock.Controller
recorder *MockPresenceGetterMockRecorder
recorder *MockNumLocalSubscribersGetterMockRecorder
}
// MockPresenceGetterMockRecorder is the mock recorder for MockPresenceGetter.
type MockPresenceGetterMockRecorder struct {
mock *MockPresenceGetter
// MockNumLocalSubscribersGetterMockRecorder is the mock recorder for MockNumLocalSubscribersGetter.
type MockNumLocalSubscribersGetterMockRecorder struct {
mock *MockNumLocalSubscribersGetter
}
// NewMockPresenceGetter creates a new mock instance.
func NewMockPresenceGetter(ctrl *gomock.Controller) *MockPresenceGetter {
mock := &MockPresenceGetter{ctrl: ctrl}
mock.recorder = &MockPresenceGetterMockRecorder{mock}
// NewMockNumLocalSubscribersGetter creates a new mock instance.
func NewMockNumLocalSubscribersGetter(ctrl *gomock.Controller) *MockNumLocalSubscribersGetter {
mock := &MockNumLocalSubscribersGetter{ctrl: ctrl}
mock.recorder = &MockNumLocalSubscribersGetterMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockPresenceGetter) EXPECT() *MockPresenceGetterMockRecorder {
func (m *MockNumLocalSubscribersGetter) EXPECT() *MockNumLocalSubscribersGetterMockRecorder {
return m.recorder
}
// GetNumSubscribers mocks base method.
func (m *MockPresenceGetter) GetNumSubscribers(arg0 string) (int, error) {
// GetNumLocalSubscribers mocks base method.
func (m *MockNumLocalSubscribersGetter) GetNumLocalSubscribers(arg0 string) (int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetNumSubscribers", arg0)
ret := m.ctrl.Call(m, "GetNumLocalSubscribers", arg0)
ret0, _ := ret[0].(int)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetNumSubscribers indicates an expected call of GetNumSubscribers.
func (mr *MockPresenceGetterMockRecorder) GetNumSubscribers(arg0 interface{}) *gomock.Call {
// GetNumLocalSubscribers indicates an expected call of GetNumLocalSubscribers.
func (mr *MockNumLocalSubscribersGetterMockRecorder) GetNumLocalSubscribers(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNumSubscribers", reflect.TypeOf((*MockPresenceGetter)(nil).GetNumSubscribers), arg0)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNumLocalSubscribers", reflect.TypeOf((*MockNumLocalSubscribersGetter)(nil).GetNumLocalSubscribers), arg0)
}
// MockStreamRunner is a mock of StreamRunner interface.