Live: experimental HA with Redis (#34851)
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user