mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-11 05:06:51 +00:00
chore(GODT-2848): Simplify User Event Service
Rather than having the services subscribe to each individual event type, have only one subscriber for the whole event object. This spreads the logic to the service through the `EventHandler` type. This is important for the next stage where the IMAP service will be required to apply events from the past.
This commit is contained in:
2
Makefile
2
Makefile
@ -284,7 +284,7 @@ mocks:
|
|||||||
mockgen --package mocks github.com/ProtonMail/proton-bridge/v3/internal/services/userevents \
|
mockgen --package mocks github.com/ProtonMail/proton-bridge/v3/internal/services/userevents \
|
||||||
EventSource,EventIDStore > internal/services/userevents/mocks/mocks.go
|
EventSource,EventIDStore > internal/services/userevents/mocks/mocks.go
|
||||||
mockgen --package userevents github.com/ProtonMail/proton-bridge/v3/internal/services/userevents \
|
mockgen --package userevents github.com/ProtonMail/proton-bridge/v3/internal/services/userevents \
|
||||||
MessageSubscriber,LabelSubscriber,AddressSubscriber,RefreshSubscriber,UserSubscriber,UserUsedSpaceSubscriber > tmp
|
EventSubscriber,MessageEventHandler,LabelEventHandler,AddressEventHandler,RefreshEventHandler,UserEventHandler,UserUsedSpaceEventHandler > tmp
|
||||||
mv tmp internal/services/userevents/mocks_test.go
|
mv tmp internal/services/userevents/mocks_test.go
|
||||||
mockgen --package mocks github.com/ProtonMail/proton-bridge/v3/internal/events EventPublisher \
|
mockgen --package mocks github.com/ProtonMail/proton-bridge/v3/internal/events EventPublisher \
|
||||||
> internal/events/mocks/mocks.go
|
> internal/events/mocks/mocks.go
|
||||||
|
|||||||
@ -73,11 +73,7 @@ type Service struct {
|
|||||||
labels *rwLabels
|
labels *rwLabels
|
||||||
addressMode usertypes.AddressMode
|
addressMode usertypes.AddressMode
|
||||||
|
|
||||||
refreshSubscriber *userevents.RefreshChanneledSubscriber
|
subscription *userevents.EventChanneledSubscriber
|
||||||
addressSubscriber *userevents.AddressChanneledSubscriber
|
|
||||||
userSubscriber *userevents.UserChanneledSubscriber
|
|
||||||
messageSubscriber *userevents.MessageChanneledSubscriber
|
|
||||||
labelSubscriber *userevents.LabelChanneledSubscriber
|
|
||||||
|
|
||||||
gluonIDProvider GluonIDProvider
|
gluonIDProvider GluonIDProvider
|
||||||
syncStateProvider SyncStateProvider
|
syncStateProvider SyncStateProvider
|
||||||
@ -95,6 +91,7 @@ type Service struct {
|
|||||||
connectors map[string]*Connector
|
connectors map[string]*Connector
|
||||||
maxSyncMemory uint64
|
maxSyncMemory uint64
|
||||||
showAllMail bool
|
showAllMail bool
|
||||||
|
syncHandler *syncHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(
|
func NewService(
|
||||||
@ -135,11 +132,7 @@ func NewService(
|
|||||||
eventProvider: eventProvider,
|
eventProvider: eventProvider,
|
||||||
eventPublisher: eventPublisher,
|
eventPublisher: eventPublisher,
|
||||||
|
|
||||||
refreshSubscriber: userevents.NewRefreshSubscriber(subscriberName),
|
subscription: userevents.NewEventSubscriber(subscriberName),
|
||||||
addressSubscriber: userevents.NewAddressSubscriber(subscriberName),
|
|
||||||
userSubscriber: userevents.NewUserSubscriber(subscriberName),
|
|
||||||
messageSubscriber: userevents.NewMessageSubscriber(subscriberName),
|
|
||||||
labelSubscriber: userevents.NewLabelSubscriber(subscriberName),
|
|
||||||
|
|
||||||
panicHandler: panicHandler,
|
panicHandler: panicHandler,
|
||||||
sendRecorder: sendRecorder,
|
sendRecorder: sendRecorder,
|
||||||
@ -241,6 +234,44 @@ func (s *Service) Close() {
|
|||||||
s.connectors = make(map[string]*Connector)
|
s.connectors = make(map[string]*Connector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) HandleRefreshEvent(ctx context.Context, _ proton.RefreshFlag) error {
|
||||||
|
s.log.Debug("handling refresh event")
|
||||||
|
|
||||||
|
if err := s.identityState.Write(func(identity *useridentity.State) error {
|
||||||
|
return identity.OnRefreshEvent(ctx)
|
||||||
|
}); err != nil {
|
||||||
|
s.log.WithError(err).Error("Failed to apply refresh event to identity state")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.syncHandler.CancelAndWait()
|
||||||
|
|
||||||
|
if err := s.removeConnectorsFromServer(ctx, s.connectors, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.syncStateProvider.ClearSyncStatus(); err != nil {
|
||||||
|
return fmt.Errorf("failed to clear sync status:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.addConnectorsToServer(ctx, s.connectors); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.syncHandler.launch(s)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) HandleUserEvent(_ context.Context, user *proton.User) error {
|
||||||
|
s.log.Debug("handling user event")
|
||||||
|
|
||||||
|
return s.identityState.Write(func(identity *useridentity.State) error {
|
||||||
|
identity.OnUserEvent(*user)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) run(ctx context.Context) { //nolint gocyclo
|
func (s *Service) run(ctx context.Context) { //nolint gocyclo
|
||||||
s.log.Info("Starting IMAP Service")
|
s.log.Info("Starting IMAP Service")
|
||||||
defer s.log.Info("Exiting IMAP Service")
|
defer s.log.Info("Exiting IMAP Service")
|
||||||
@ -248,21 +279,21 @@ func (s *Service) run(ctx context.Context) { //nolint gocyclo
|
|||||||
defer s.cpc.Close()
|
defer s.cpc.Close()
|
||||||
defer s.eventSubscription.Remove(s.eventWatcher)
|
defer s.eventSubscription.Remove(s.eventWatcher)
|
||||||
|
|
||||||
syncHandler := newSyncHandler(ctx, s.panicHandler)
|
s.syncHandler = newSyncHandler(ctx, s.panicHandler)
|
||||||
defer syncHandler.Close()
|
defer s.syncHandler.Close()
|
||||||
|
|
||||||
syncHandler.launch(s)
|
s.syncHandler.launch(s)
|
||||||
|
|
||||||
subscription := userevents.Subscription{
|
eventHandler := userevents.EventHandler{
|
||||||
User: s.userSubscriber,
|
UserHandler: s,
|
||||||
Refresh: s.refreshSubscriber,
|
AddressHandler: s,
|
||||||
Address: s.addressSubscriber,
|
RefreshHandler: s,
|
||||||
Labels: s.labelSubscriber,
|
LabelHandler: s,
|
||||||
Messages: s.messageSubscriber,
|
MessageHandler: s,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.eventProvider.Subscribe(subscription)
|
s.eventProvider.Subscribe(s.subscription)
|
||||||
defer s.eventProvider.Unsubscribe(subscription)
|
defer s.eventProvider.Unsubscribe(s.subscription)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -275,25 +306,25 @@ func (s *Service) run(ctx context.Context) { //nolint gocyclo
|
|||||||
}
|
}
|
||||||
switch r := req.Value().(type) {
|
switch r := req.Value().(type) {
|
||||||
case *setAddressModeReq:
|
case *setAddressModeReq:
|
||||||
err := s.setAddressMode(ctx, syncHandler, r.mode)
|
err := s.setAddressMode(ctx, s.syncHandler, r.mode)
|
||||||
req.Reply(ctx, nil, err)
|
req.Reply(ctx, nil, err)
|
||||||
|
|
||||||
case *resyncReq:
|
case *resyncReq:
|
||||||
s.log.Info("Received resync request, handling as refresh event")
|
s.log.Info("Received resync request, handling as refresh event")
|
||||||
err := s.onRefreshEvent(ctx, syncHandler)
|
err := s.HandleRefreshEvent(ctx, 0)
|
||||||
req.Reply(ctx, nil, err)
|
req.Reply(ctx, nil, err)
|
||||||
s.log.Info("Resync reply sent, handling as refresh event")
|
s.log.Info("Resync reply sent, handling as refresh event")
|
||||||
|
|
||||||
case *cancelSyncReq:
|
case *cancelSyncReq:
|
||||||
s.log.Info("Cancelling sync")
|
s.log.Info("Cancelling sync")
|
||||||
syncHandler.Cancel()
|
s.syncHandler.Cancel()
|
||||||
req.Reply(ctx, nil, nil)
|
req.Reply(ctx, nil, nil)
|
||||||
|
|
||||||
case *resumeSyncReq:
|
case *resumeSyncReq:
|
||||||
s.log.Info("Resuming sync")
|
s.log.Info("Resuming sync")
|
||||||
// Cancel previous run, if any, just in case.
|
// Cancel previous run, if any, just in case.
|
||||||
syncHandler.CancelAndWait()
|
s.syncHandler.CancelAndWait()
|
||||||
syncHandler.launch(s)
|
s.syncHandler.launch(s)
|
||||||
req.Reply(ctx, nil, nil)
|
req.Reply(ctx, nil, nil)
|
||||||
case *getLabelsReq:
|
case *getLabelsReq:
|
||||||
labels := s.labels.GetLabelMap()
|
labels := s.labels.GetLabelMap()
|
||||||
@ -319,7 +350,7 @@ func (s *Service) run(ctx context.Context) { //nolint gocyclo
|
|||||||
s.log.Error("Received unknown request")
|
s.log.Error("Received unknown request")
|
||||||
}
|
}
|
||||||
|
|
||||||
case err, ok := <-syncHandler.OnSyncFinishedCH():
|
case err, ok := <-s.syncHandler.OnSyncFinishedCH():
|
||||||
{
|
{
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
@ -334,46 +365,18 @@ func (s *Service) run(ctx context.Context) { //nolint gocyclo
|
|||||||
s.eventProvider.Resume()
|
s.eventProvider.Resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
case update, ok := <-syncHandler.updater.ch:
|
case update, ok := <-s.syncHandler.updater.ch:
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s.onSyncUpdate(ctx, update)
|
s.onSyncUpdate(ctx, update)
|
||||||
|
|
||||||
case e, ok := <-s.userSubscriber.OnEventCh():
|
case e, ok := <-s.subscription.OnEventCh():
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
e.Consume(func(user proton.User) error {
|
e.Consume(func(event proton.Event) error {
|
||||||
return s.onUserEvent(user)
|
return eventHandler.OnEvent(ctx, event)
|
||||||
})
|
|
||||||
case e, ok := <-s.addressSubscriber.OnEventCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
e.Consume(func(events []proton.AddressEvent) error {
|
|
||||||
return s.onAddressEvent(ctx, events)
|
|
||||||
})
|
|
||||||
case e, ok := <-s.labelSubscriber.OnEventCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
e.Consume(func(events []proton.LabelEvent) error {
|
|
||||||
return s.onLabelEvent(ctx, events)
|
|
||||||
})
|
|
||||||
case e, ok := <-s.messageSubscriber.OnEventCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
e.Consume(func(events []proton.MessageEvent) error {
|
|
||||||
return s.onMessageEvent(ctx, events)
|
|
||||||
})
|
|
||||||
case e, ok := <-s.refreshSubscriber.OnEventCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
e.Consume(func(_ proton.RefreshFlag) error {
|
|
||||||
return s.onRefreshEvent(ctx, syncHandler)
|
|
||||||
})
|
})
|
||||||
case e, ok := <-s.eventWatcher.GetChannel():
|
case e, ok := <-s.eventWatcher.GetChannel():
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -389,43 +392,6 @@ func (s *Service) run(ctx context.Context) { //nolint gocyclo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) onRefreshEvent(ctx context.Context, handler *syncHandler) error {
|
|
||||||
s.log.Debug("handling refresh event")
|
|
||||||
|
|
||||||
if err := s.identityState.Write(func(identity *useridentity.State) error {
|
|
||||||
return identity.OnRefreshEvent(ctx)
|
|
||||||
}); err != nil {
|
|
||||||
s.log.WithError(err).Error("Failed to apply refresh event to identity state")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.CancelAndWait()
|
|
||||||
|
|
||||||
if err := s.removeConnectorsFromServer(ctx, s.connectors, true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.syncStateProvider.ClearSyncStatus(); err != nil {
|
|
||||||
return fmt.Errorf("failed to clear sync status:%w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.addConnectorsToServer(ctx, s.connectors); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.launch(s)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) onUserEvent(user proton.User) error {
|
|
||||||
s.log.Debug("handling user event")
|
|
||||||
return s.identityState.Write(func(identity *useridentity.State) error {
|
|
||||||
identity.OnUserEvent(user)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) buildConnectors() (map[string]*Connector, error) {
|
func (s *Service) buildConnectors() (map[string]*Connector, error) {
|
||||||
connectors := make(map[string]*Connector)
|
connectors := make(map[string]*Connector)
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import (
|
|||||||
"github.com/ProtonMail/proton-bridge/v3/internal/usertypes"
|
"github.com/ProtonMail/proton-bridge/v3/internal/usertypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) onAddressEvent(ctx context.Context, events []proton.AddressEvent) error {
|
func (s *Service) HandleAddressEvents(ctx context.Context, events []proton.AddressEvent) error {
|
||||||
s.log.Debug("handling address event")
|
s.log.Debug("handling address event")
|
||||||
|
|
||||||
if s.addressMode == usertypes.AddressModeCombined {
|
if s.addressMode == usertypes.AddressModeCombined {
|
||||||
|
|||||||
@ -32,7 +32,7 @@ import (
|
|||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) onLabelEvent(ctx context.Context, events []proton.LabelEvent) error {
|
func (s *Service) HandleLabelEvents(ctx context.Context, events []proton.LabelEvent) error {
|
||||||
s.log.Debug("handling label event")
|
s.log.Debug("handling label event")
|
||||||
|
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
|
|||||||
@ -36,7 +36,7 @@ import (
|
|||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) onMessageEvent(ctx context.Context, events []proton.MessageEvent) error {
|
func (s *Service) HandleMessageEvents(ctx context.Context, events []proton.MessageEvent) error {
|
||||||
s.log.Debug("handling message event")
|
s.log.Debug("handling message event")
|
||||||
|
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
|
|||||||
@ -57,10 +57,8 @@ type Service struct {
|
|||||||
identityState *useridentity.State
|
identityState *useridentity.State
|
||||||
telemetry Telemetry
|
telemetry Telemetry
|
||||||
|
|
||||||
eventService userevents.Subscribable
|
eventService userevents.Subscribable
|
||||||
refreshSubscriber *userevents.RefreshChanneledSubscriber
|
subscription *userevents.EventChanneledSubscriber
|
||||||
addressSubscriber *userevents.AddressChanneledSubscriber
|
|
||||||
userSubscriber *userevents.UserChanneledSubscriber
|
|
||||||
|
|
||||||
addressMode usertypes.AddressMode
|
addressMode usertypes.AddressMode
|
||||||
serverManager ServerManager
|
serverManager ServerManager
|
||||||
@ -100,9 +98,7 @@ func NewService(
|
|||||||
identityState: identityState,
|
identityState: identityState,
|
||||||
eventService: eventService,
|
eventService: eventService,
|
||||||
|
|
||||||
refreshSubscriber: userevents.NewRefreshSubscriber(subscriberName),
|
subscription: userevents.NewEventSubscriber(subscriberName),
|
||||||
userSubscriber: userevents.NewUserSubscriber(subscriberName),
|
|
||||||
addressSubscriber: userevents.NewAddressSubscriber(subscriberName),
|
|
||||||
|
|
||||||
addressMode: mode,
|
addressMode: mode,
|
||||||
serverManager: serverManager,
|
serverManager: serverManager,
|
||||||
@ -168,19 +164,38 @@ func (s *Service) UserID() string {
|
|||||||
return s.userID
|
return s.userID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) HandleRefreshEvent(ctx context.Context, _ proton.RefreshFlag) error {
|
||||||
|
s.log.Debug("Handling refresh event")
|
||||||
|
return s.identityState.OnRefreshEvent(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) HandleAddressEvents(_ context.Context, events []proton.AddressEvent) error {
|
||||||
|
s.log.Debug("Handling Address Event")
|
||||||
|
s.identityState.OnAddressEvents(events)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) HandleUserEvent(_ context.Context, user *proton.User) error {
|
||||||
|
s.log.Debug("Handling user event")
|
||||||
|
s.identityState.OnUserEvent(*user)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) run(ctx context.Context) {
|
func (s *Service) run(ctx context.Context) {
|
||||||
s.log.Info("Starting service main loop")
|
s.log.Info("Starting service main loop")
|
||||||
defer s.log.Info("Exiting service main loop")
|
defer s.log.Info("Exiting service main loop")
|
||||||
defer s.cpc.Close()
|
defer s.cpc.Close()
|
||||||
|
|
||||||
subscription := userevents.Subscription{
|
eventHandler := userevents.EventHandler{
|
||||||
User: s.userSubscriber,
|
AddressHandler: s,
|
||||||
Refresh: s.refreshSubscriber,
|
RefreshHandler: s,
|
||||||
Address: s.addressSubscriber,
|
UserHandler: s,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.eventService.Subscribe(subscription)
|
s.eventService.Subscribe(s.subscription)
|
||||||
defer s.eventService.Unsubscribe(subscription)
|
defer s.eventService.Unsubscribe(s.subscription)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -219,34 +234,12 @@ func (s *Service) run(ctx context.Context) {
|
|||||||
default:
|
default:
|
||||||
s.log.Error("Received unknown request")
|
s.log.Error("Received unknown request")
|
||||||
}
|
}
|
||||||
case e, ok := <-s.userSubscriber.OnEventCh():
|
case e, ok := <-s.subscription.OnEventCh():
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
e.Consume(func(event proton.Event) error {
|
||||||
s.log.Debug("Handling user event")
|
return eventHandler.OnEvent(ctx, event)
|
||||||
e.Consume(func(user proton.User) error {
|
|
||||||
s.identityState.OnUserEvent(user)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
case e, ok := <-s.refreshSubscriber.OnEventCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
s.log.Debug("Handling refresh event")
|
|
||||||
e.Consume(func(_ proton.RefreshFlag) error {
|
|
||||||
return s.identityState.OnRefreshEvent(ctx)
|
|
||||||
})
|
|
||||||
case e, ok := <-s.addressSubscriber.OnEventCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
s.log.Debug("Handling Address Event")
|
|
||||||
e.Consume(func(evt []proton.AddressEvent) error {
|
|
||||||
s.identityState.OnAddressEvents(evt)
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// Code generated by MockGen. DO NOT EDIT.
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: github.com/ProtonMail/proton-bridge/v3/internal/services/userevents (interfaces: MessageSubscriber,LabelSubscriber,AddressSubscriber,RefreshSubscriber,UserSubscriber,UserUsedSpaceSubscriber)
|
// Source: github.com/ProtonMail/proton-bridge/v3/internal/services/userevents (interfaces: EventSubscriber,MessageEventHandler,LabelEventHandler,AddressEventHandler,RefreshEventHandler,UserEventHandler,UserUsedSpaceEventHandler)
|
||||||
|
|
||||||
// Package userevents is a generated GoMock package.
|
// Package userevents is a generated GoMock package.
|
||||||
package userevents
|
package userevents
|
||||||
@ -12,55 +12,55 @@ import (
|
|||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockMessageSubscriber is a mock of MessageSubscriber interface.
|
// MockEventSubscriber is a mock of EventSubscriber interface.
|
||||||
type MockMessageSubscriber struct {
|
type MockEventSubscriber struct {
|
||||||
ctrl *gomock.Controller
|
ctrl *gomock.Controller
|
||||||
recorder *MockMessageSubscriberMockRecorder
|
recorder *MockEventSubscriberMockRecorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockMessageSubscriberMockRecorder is the mock recorder for MockMessageSubscriber.
|
// MockEventSubscriberMockRecorder is the mock recorder for MockEventSubscriber.
|
||||||
type MockMessageSubscriberMockRecorder struct {
|
type MockEventSubscriberMockRecorder struct {
|
||||||
mock *MockMessageSubscriber
|
mock *MockEventSubscriber
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMockMessageSubscriber creates a new mock instance.
|
// NewMockEventSubscriber creates a new mock instance.
|
||||||
func NewMockMessageSubscriber(ctrl *gomock.Controller) *MockMessageSubscriber {
|
func NewMockEventSubscriber(ctrl *gomock.Controller) *MockEventSubscriber {
|
||||||
mock := &MockMessageSubscriber{ctrl: ctrl}
|
mock := &MockEventSubscriber{ctrl: ctrl}
|
||||||
mock.recorder = &MockMessageSubscriberMockRecorder{mock}
|
mock.recorder = &MockEventSubscriberMockRecorder{mock}
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
func (m *MockMessageSubscriber) EXPECT() *MockMessageSubscriberMockRecorder {
|
func (m *MockEventSubscriber) EXPECT() *MockEventSubscriberMockRecorder {
|
||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// cancel mocks base method.
|
// cancel mocks base method.
|
||||||
func (m *MockMessageSubscriber) cancel() {
|
func (m *MockEventSubscriber) cancel() {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
m.ctrl.Call(m, "cancel")
|
m.ctrl.Call(m, "cancel")
|
||||||
}
|
}
|
||||||
|
|
||||||
// cancel indicates an expected call of cancel.
|
// cancel indicates an expected call of cancel.
|
||||||
func (mr *MockMessageSubscriberMockRecorder) cancel() *gomock.Call {
|
func (mr *MockEventSubscriberMockRecorder) cancel() *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "cancel", reflect.TypeOf((*MockMessageSubscriber)(nil).cancel))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "cancel", reflect.TypeOf((*MockEventSubscriber)(nil).cancel))
|
||||||
}
|
}
|
||||||
|
|
||||||
// close mocks base method.
|
// close mocks base method.
|
||||||
func (m *MockMessageSubscriber) close() {
|
func (m *MockEventSubscriber) close() {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
m.ctrl.Call(m, "close")
|
m.ctrl.Call(m, "close")
|
||||||
}
|
}
|
||||||
|
|
||||||
// close indicates an expected call of close.
|
// close indicates an expected call of close.
|
||||||
func (mr *MockMessageSubscriberMockRecorder) close() *gomock.Call {
|
func (mr *MockEventSubscriberMockRecorder) close() *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "close", reflect.TypeOf((*MockMessageSubscriber)(nil).close))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "close", reflect.TypeOf((*MockEventSubscriber)(nil).close))
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle mocks base method.
|
// handle mocks base method.
|
||||||
func (m *MockMessageSubscriber) handle(arg0 context.Context, arg1 []proton.MessageEvent) error {
|
func (m *MockEventSubscriber) handle(arg0 context.Context, arg1 proton.Event) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "handle", arg0, arg1)
|
ret := m.ctrl.Call(m, "handle", arg0, arg1)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
@ -68,13 +68,13 @@ func (m *MockMessageSubscriber) handle(arg0 context.Context, arg1 []proton.Messa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle indicates an expected call of handle.
|
// handle indicates an expected call of handle.
|
||||||
func (mr *MockMessageSubscriberMockRecorder) handle(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockEventSubscriberMockRecorder) handle(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "handle", reflect.TypeOf((*MockMessageSubscriber)(nil).handle), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "handle", reflect.TypeOf((*MockEventSubscriber)(nil).handle), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// name mocks base method.
|
// name mocks base method.
|
||||||
func (m *MockMessageSubscriber) name() string {
|
func (m *MockEventSubscriber) name() string {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "name")
|
ret := m.ctrl.Call(m, "name")
|
||||||
ret0, _ := ret[0].(string)
|
ret0, _ := ret[0].(string)
|
||||||
@ -82,382 +82,229 @@ func (m *MockMessageSubscriber) name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// name indicates an expected call of name.
|
// name indicates an expected call of name.
|
||||||
func (mr *MockMessageSubscriberMockRecorder) name() *gomock.Call {
|
func (mr *MockEventSubscriberMockRecorder) name() *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "name", reflect.TypeOf((*MockMessageSubscriber)(nil).name))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "name", reflect.TypeOf((*MockEventSubscriber)(nil).name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockLabelSubscriber is a mock of LabelSubscriber interface.
|
// MockMessageEventHandler is a mock of MessageEventHandler interface.
|
||||||
type MockLabelSubscriber struct {
|
type MockMessageEventHandler struct {
|
||||||
ctrl *gomock.Controller
|
ctrl *gomock.Controller
|
||||||
recorder *MockLabelSubscriberMockRecorder
|
recorder *MockMessageEventHandlerMockRecorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockLabelSubscriberMockRecorder is the mock recorder for MockLabelSubscriber.
|
// MockMessageEventHandlerMockRecorder is the mock recorder for MockMessageEventHandler.
|
||||||
type MockLabelSubscriberMockRecorder struct {
|
type MockMessageEventHandlerMockRecorder struct {
|
||||||
mock *MockLabelSubscriber
|
mock *MockMessageEventHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMockLabelSubscriber creates a new mock instance.
|
// NewMockMessageEventHandler creates a new mock instance.
|
||||||
func NewMockLabelSubscriber(ctrl *gomock.Controller) *MockLabelSubscriber {
|
func NewMockMessageEventHandler(ctrl *gomock.Controller) *MockMessageEventHandler {
|
||||||
mock := &MockLabelSubscriber{ctrl: ctrl}
|
mock := &MockMessageEventHandler{ctrl: ctrl}
|
||||||
mock.recorder = &MockLabelSubscriberMockRecorder{mock}
|
mock.recorder = &MockMessageEventHandlerMockRecorder{mock}
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
func (m *MockLabelSubscriber) EXPECT() *MockLabelSubscriberMockRecorder {
|
func (m *MockMessageEventHandler) EXPECT() *MockMessageEventHandlerMockRecorder {
|
||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// cancel mocks base method.
|
// HandleMessageEvents mocks base method.
|
||||||
func (m *MockLabelSubscriber) cancel() {
|
func (m *MockMessageEventHandler) HandleMessageEvents(arg0 context.Context, arg1 []proton.MessageEvent) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
m.ctrl.Call(m, "cancel")
|
ret := m.ctrl.Call(m, "HandleMessageEvents", arg0, arg1)
|
||||||
}
|
|
||||||
|
|
||||||
// cancel indicates an expected call of cancel.
|
|
||||||
func (mr *MockLabelSubscriberMockRecorder) cancel() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "cancel", reflect.TypeOf((*MockLabelSubscriber)(nil).cancel))
|
|
||||||
}
|
|
||||||
|
|
||||||
// close mocks base method.
|
|
||||||
func (m *MockLabelSubscriber) close() {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
m.ctrl.Call(m, "close")
|
|
||||||
}
|
|
||||||
|
|
||||||
// close indicates an expected call of close.
|
|
||||||
func (mr *MockLabelSubscriberMockRecorder) close() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "close", reflect.TypeOf((*MockLabelSubscriber)(nil).close))
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle mocks base method.
|
|
||||||
func (m *MockLabelSubscriber) handle(arg0 context.Context, arg1 []proton.LabelEvent) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "handle", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle indicates an expected call of handle.
|
// HandleMessageEvents indicates an expected call of HandleMessageEvents.
|
||||||
func (mr *MockLabelSubscriberMockRecorder) handle(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockMessageEventHandlerMockRecorder) HandleMessageEvents(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "handle", reflect.TypeOf((*MockLabelSubscriber)(nil).handle), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleMessageEvents", reflect.TypeOf((*MockMessageEventHandler)(nil).HandleMessageEvents), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// name mocks base method.
|
// MockLabelEventHandler is a mock of LabelEventHandler interface.
|
||||||
func (m *MockLabelSubscriber) name() string {
|
type MockLabelEventHandler struct {
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "name")
|
|
||||||
ret0, _ := ret[0].(string)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// name indicates an expected call of name.
|
|
||||||
func (mr *MockLabelSubscriberMockRecorder) name() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "name", reflect.TypeOf((*MockLabelSubscriber)(nil).name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// MockAddressSubscriber is a mock of AddressSubscriber interface.
|
|
||||||
type MockAddressSubscriber struct {
|
|
||||||
ctrl *gomock.Controller
|
ctrl *gomock.Controller
|
||||||
recorder *MockAddressSubscriberMockRecorder
|
recorder *MockLabelEventHandlerMockRecorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockAddressSubscriberMockRecorder is the mock recorder for MockAddressSubscriber.
|
// MockLabelEventHandlerMockRecorder is the mock recorder for MockLabelEventHandler.
|
||||||
type MockAddressSubscriberMockRecorder struct {
|
type MockLabelEventHandlerMockRecorder struct {
|
||||||
mock *MockAddressSubscriber
|
mock *MockLabelEventHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMockAddressSubscriber creates a new mock instance.
|
// NewMockLabelEventHandler creates a new mock instance.
|
||||||
func NewMockAddressSubscriber(ctrl *gomock.Controller) *MockAddressSubscriber {
|
func NewMockLabelEventHandler(ctrl *gomock.Controller) *MockLabelEventHandler {
|
||||||
mock := &MockAddressSubscriber{ctrl: ctrl}
|
mock := &MockLabelEventHandler{ctrl: ctrl}
|
||||||
mock.recorder = &MockAddressSubscriberMockRecorder{mock}
|
mock.recorder = &MockLabelEventHandlerMockRecorder{mock}
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
func (m *MockAddressSubscriber) EXPECT() *MockAddressSubscriberMockRecorder {
|
func (m *MockLabelEventHandler) EXPECT() *MockLabelEventHandlerMockRecorder {
|
||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// cancel mocks base method.
|
// HandleLabelEvents mocks base method.
|
||||||
func (m *MockAddressSubscriber) cancel() {
|
func (m *MockLabelEventHandler) HandleLabelEvents(arg0 context.Context, arg1 []proton.LabelEvent) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
m.ctrl.Call(m, "cancel")
|
ret := m.ctrl.Call(m, "HandleLabelEvents", arg0, arg1)
|
||||||
}
|
|
||||||
|
|
||||||
// cancel indicates an expected call of cancel.
|
|
||||||
func (mr *MockAddressSubscriberMockRecorder) cancel() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "cancel", reflect.TypeOf((*MockAddressSubscriber)(nil).cancel))
|
|
||||||
}
|
|
||||||
|
|
||||||
// close mocks base method.
|
|
||||||
func (m *MockAddressSubscriber) close() {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
m.ctrl.Call(m, "close")
|
|
||||||
}
|
|
||||||
|
|
||||||
// close indicates an expected call of close.
|
|
||||||
func (mr *MockAddressSubscriberMockRecorder) close() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "close", reflect.TypeOf((*MockAddressSubscriber)(nil).close))
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle mocks base method.
|
|
||||||
func (m *MockAddressSubscriber) handle(arg0 context.Context, arg1 []proton.AddressEvent) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "handle", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle indicates an expected call of handle.
|
// HandleLabelEvents indicates an expected call of HandleLabelEvents.
|
||||||
func (mr *MockAddressSubscriberMockRecorder) handle(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockLabelEventHandlerMockRecorder) HandleLabelEvents(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "handle", reflect.TypeOf((*MockAddressSubscriber)(nil).handle), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleLabelEvents", reflect.TypeOf((*MockLabelEventHandler)(nil).HandleLabelEvents), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// name mocks base method.
|
// MockAddressEventHandler is a mock of AddressEventHandler interface.
|
||||||
func (m *MockAddressSubscriber) name() string {
|
type MockAddressEventHandler struct {
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "name")
|
|
||||||
ret0, _ := ret[0].(string)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// name indicates an expected call of name.
|
|
||||||
func (mr *MockAddressSubscriberMockRecorder) name() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "name", reflect.TypeOf((*MockAddressSubscriber)(nil).name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// MockRefreshSubscriber is a mock of RefreshSubscriber interface.
|
|
||||||
type MockRefreshSubscriber struct {
|
|
||||||
ctrl *gomock.Controller
|
ctrl *gomock.Controller
|
||||||
recorder *MockRefreshSubscriberMockRecorder
|
recorder *MockAddressEventHandlerMockRecorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockRefreshSubscriberMockRecorder is the mock recorder for MockRefreshSubscriber.
|
// MockAddressEventHandlerMockRecorder is the mock recorder for MockAddressEventHandler.
|
||||||
type MockRefreshSubscriberMockRecorder struct {
|
type MockAddressEventHandlerMockRecorder struct {
|
||||||
mock *MockRefreshSubscriber
|
mock *MockAddressEventHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMockRefreshSubscriber creates a new mock instance.
|
// NewMockAddressEventHandler creates a new mock instance.
|
||||||
func NewMockRefreshSubscriber(ctrl *gomock.Controller) *MockRefreshSubscriber {
|
func NewMockAddressEventHandler(ctrl *gomock.Controller) *MockAddressEventHandler {
|
||||||
mock := &MockRefreshSubscriber{ctrl: ctrl}
|
mock := &MockAddressEventHandler{ctrl: ctrl}
|
||||||
mock.recorder = &MockRefreshSubscriberMockRecorder{mock}
|
mock.recorder = &MockAddressEventHandlerMockRecorder{mock}
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
func (m *MockRefreshSubscriber) EXPECT() *MockRefreshSubscriberMockRecorder {
|
func (m *MockAddressEventHandler) EXPECT() *MockAddressEventHandlerMockRecorder {
|
||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// cancel mocks base method.
|
// HandleAddressEvents mocks base method.
|
||||||
func (m *MockRefreshSubscriber) cancel() {
|
func (m *MockAddressEventHandler) HandleAddressEvents(arg0 context.Context, arg1 []proton.AddressEvent) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
m.ctrl.Call(m, "cancel")
|
ret := m.ctrl.Call(m, "HandleAddressEvents", arg0, arg1)
|
||||||
}
|
|
||||||
|
|
||||||
// cancel indicates an expected call of cancel.
|
|
||||||
func (mr *MockRefreshSubscriberMockRecorder) cancel() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "cancel", reflect.TypeOf((*MockRefreshSubscriber)(nil).cancel))
|
|
||||||
}
|
|
||||||
|
|
||||||
// close mocks base method.
|
|
||||||
func (m *MockRefreshSubscriber) close() {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
m.ctrl.Call(m, "close")
|
|
||||||
}
|
|
||||||
|
|
||||||
// close indicates an expected call of close.
|
|
||||||
func (mr *MockRefreshSubscriberMockRecorder) close() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "close", reflect.TypeOf((*MockRefreshSubscriber)(nil).close))
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle mocks base method.
|
|
||||||
func (m *MockRefreshSubscriber) handle(arg0 context.Context, arg1 proton.RefreshFlag) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "handle", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle indicates an expected call of handle.
|
// HandleAddressEvents indicates an expected call of HandleAddressEvents.
|
||||||
func (mr *MockRefreshSubscriberMockRecorder) handle(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockAddressEventHandlerMockRecorder) HandleAddressEvents(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "handle", reflect.TypeOf((*MockRefreshSubscriber)(nil).handle), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleAddressEvents", reflect.TypeOf((*MockAddressEventHandler)(nil).HandleAddressEvents), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// name mocks base method.
|
// MockRefreshEventHandler is a mock of RefreshEventHandler interface.
|
||||||
func (m *MockRefreshSubscriber) name() string {
|
type MockRefreshEventHandler struct {
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "name")
|
|
||||||
ret0, _ := ret[0].(string)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// name indicates an expected call of name.
|
|
||||||
func (mr *MockRefreshSubscriberMockRecorder) name() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "name", reflect.TypeOf((*MockRefreshSubscriber)(nil).name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// MockUserSubscriber is a mock of UserSubscriber interface.
|
|
||||||
type MockUserSubscriber struct {
|
|
||||||
ctrl *gomock.Controller
|
ctrl *gomock.Controller
|
||||||
recorder *MockUserSubscriberMockRecorder
|
recorder *MockRefreshEventHandlerMockRecorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockUserSubscriberMockRecorder is the mock recorder for MockUserSubscriber.
|
// MockRefreshEventHandlerMockRecorder is the mock recorder for MockRefreshEventHandler.
|
||||||
type MockUserSubscriberMockRecorder struct {
|
type MockRefreshEventHandlerMockRecorder struct {
|
||||||
mock *MockUserSubscriber
|
mock *MockRefreshEventHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMockUserSubscriber creates a new mock instance.
|
// NewMockRefreshEventHandler creates a new mock instance.
|
||||||
func NewMockUserSubscriber(ctrl *gomock.Controller) *MockUserSubscriber {
|
func NewMockRefreshEventHandler(ctrl *gomock.Controller) *MockRefreshEventHandler {
|
||||||
mock := &MockUserSubscriber{ctrl: ctrl}
|
mock := &MockRefreshEventHandler{ctrl: ctrl}
|
||||||
mock.recorder = &MockUserSubscriberMockRecorder{mock}
|
mock.recorder = &MockRefreshEventHandlerMockRecorder{mock}
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
func (m *MockUserSubscriber) EXPECT() *MockUserSubscriberMockRecorder {
|
func (m *MockRefreshEventHandler) EXPECT() *MockRefreshEventHandlerMockRecorder {
|
||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// cancel mocks base method.
|
// HandleRefreshEvent mocks base method.
|
||||||
func (m *MockUserSubscriber) cancel() {
|
func (m *MockRefreshEventHandler) HandleRefreshEvent(arg0 context.Context, arg1 proton.RefreshFlag) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
m.ctrl.Call(m, "cancel")
|
ret := m.ctrl.Call(m, "HandleRefreshEvent", arg0, arg1)
|
||||||
}
|
|
||||||
|
|
||||||
// cancel indicates an expected call of cancel.
|
|
||||||
func (mr *MockUserSubscriberMockRecorder) cancel() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "cancel", reflect.TypeOf((*MockUserSubscriber)(nil).cancel))
|
|
||||||
}
|
|
||||||
|
|
||||||
// close mocks base method.
|
|
||||||
func (m *MockUserSubscriber) close() {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
m.ctrl.Call(m, "close")
|
|
||||||
}
|
|
||||||
|
|
||||||
// close indicates an expected call of close.
|
|
||||||
func (mr *MockUserSubscriberMockRecorder) close() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "close", reflect.TypeOf((*MockUserSubscriber)(nil).close))
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle mocks base method.
|
|
||||||
func (m *MockUserSubscriber) handle(arg0 context.Context, arg1 proton.User) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "handle", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle indicates an expected call of handle.
|
// HandleRefreshEvent indicates an expected call of HandleRefreshEvent.
|
||||||
func (mr *MockUserSubscriberMockRecorder) handle(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockRefreshEventHandlerMockRecorder) HandleRefreshEvent(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "handle", reflect.TypeOf((*MockUserSubscriber)(nil).handle), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleRefreshEvent", reflect.TypeOf((*MockRefreshEventHandler)(nil).HandleRefreshEvent), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// name mocks base method.
|
// MockUserEventHandler is a mock of UserEventHandler interface.
|
||||||
func (m *MockUserSubscriber) name() string {
|
type MockUserEventHandler struct {
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "name")
|
|
||||||
ret0, _ := ret[0].(string)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// name indicates an expected call of name.
|
|
||||||
func (mr *MockUserSubscriberMockRecorder) name() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "name", reflect.TypeOf((*MockUserSubscriber)(nil).name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// MockUserUsedSpaceSubscriber is a mock of UserUsedSpaceSubscriber interface.
|
|
||||||
type MockUserUsedSpaceSubscriber struct {
|
|
||||||
ctrl *gomock.Controller
|
ctrl *gomock.Controller
|
||||||
recorder *MockUserUsedSpaceSubscriberMockRecorder
|
recorder *MockUserEventHandlerMockRecorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockUserUsedSpaceSubscriberMockRecorder is the mock recorder for MockUserUsedSpaceSubscriber.
|
// MockUserEventHandlerMockRecorder is the mock recorder for MockUserEventHandler.
|
||||||
type MockUserUsedSpaceSubscriberMockRecorder struct {
|
type MockUserEventHandlerMockRecorder struct {
|
||||||
mock *MockUserUsedSpaceSubscriber
|
mock *MockUserEventHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMockUserUsedSpaceSubscriber creates a new mock instance.
|
// NewMockUserEventHandler creates a new mock instance.
|
||||||
func NewMockUserUsedSpaceSubscriber(ctrl *gomock.Controller) *MockUserUsedSpaceSubscriber {
|
func NewMockUserEventHandler(ctrl *gomock.Controller) *MockUserEventHandler {
|
||||||
mock := &MockUserUsedSpaceSubscriber{ctrl: ctrl}
|
mock := &MockUserEventHandler{ctrl: ctrl}
|
||||||
mock.recorder = &MockUserUsedSpaceSubscriberMockRecorder{mock}
|
mock.recorder = &MockUserEventHandlerMockRecorder{mock}
|
||||||
return mock
|
return mock
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
func (m *MockUserUsedSpaceSubscriber) EXPECT() *MockUserUsedSpaceSubscriberMockRecorder {
|
func (m *MockUserEventHandler) EXPECT() *MockUserEventHandlerMockRecorder {
|
||||||
return m.recorder
|
return m.recorder
|
||||||
}
|
}
|
||||||
|
|
||||||
// cancel mocks base method.
|
// HandleUserEvent mocks base method.
|
||||||
func (m *MockUserUsedSpaceSubscriber) cancel() {
|
func (m *MockUserEventHandler) HandleUserEvent(arg0 context.Context, arg1 *proton.User) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
m.ctrl.Call(m, "cancel")
|
ret := m.ctrl.Call(m, "HandleUserEvent", arg0, arg1)
|
||||||
}
|
|
||||||
|
|
||||||
// cancel indicates an expected call of cancel.
|
|
||||||
func (mr *MockUserUsedSpaceSubscriberMockRecorder) cancel() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "cancel", reflect.TypeOf((*MockUserUsedSpaceSubscriber)(nil).cancel))
|
|
||||||
}
|
|
||||||
|
|
||||||
// close mocks base method.
|
|
||||||
func (m *MockUserUsedSpaceSubscriber) close() {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
m.ctrl.Call(m, "close")
|
|
||||||
}
|
|
||||||
|
|
||||||
// close indicates an expected call of close.
|
|
||||||
func (mr *MockUserUsedSpaceSubscriberMockRecorder) close() *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "close", reflect.TypeOf((*MockUserUsedSpaceSubscriber)(nil).close))
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle mocks base method.
|
|
||||||
func (m *MockUserUsedSpaceSubscriber) handle(arg0 context.Context, arg1 int) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "handle", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle indicates an expected call of handle.
|
// HandleUserEvent indicates an expected call of HandleUserEvent.
|
||||||
func (mr *MockUserUsedSpaceSubscriberMockRecorder) handle(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockUserEventHandlerMockRecorder) HandleUserEvent(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "handle", reflect.TypeOf((*MockUserUsedSpaceSubscriber)(nil).handle), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleUserEvent", reflect.TypeOf((*MockUserEventHandler)(nil).HandleUserEvent), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// name mocks base method.
|
// MockUserUsedSpaceEventHandler is a mock of UserUsedSpaceEventHandler interface.
|
||||||
func (m *MockUserUsedSpaceSubscriber) name() string {
|
type MockUserUsedSpaceEventHandler struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockUserUsedSpaceEventHandlerMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockUserUsedSpaceEventHandlerMockRecorder is the mock recorder for MockUserUsedSpaceEventHandler.
|
||||||
|
type MockUserUsedSpaceEventHandlerMockRecorder struct {
|
||||||
|
mock *MockUserUsedSpaceEventHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockUserUsedSpaceEventHandler creates a new mock instance.
|
||||||
|
func NewMockUserUsedSpaceEventHandler(ctrl *gomock.Controller) *MockUserUsedSpaceEventHandler {
|
||||||
|
mock := &MockUserUsedSpaceEventHandler{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockUserUsedSpaceEventHandlerMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockUserUsedSpaceEventHandler) EXPECT() *MockUserUsedSpaceEventHandlerMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleUsedSpaceEvent mocks base method.
|
||||||
|
func (m *MockUserUsedSpaceEventHandler) HandleUsedSpaceEvent(arg0 context.Context, arg1 int) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "name")
|
ret := m.ctrl.Call(m, "HandleUsedSpaceEvent", arg0, arg1)
|
||||||
ret0, _ := ret[0].(string)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// name indicates an expected call of name.
|
// HandleUsedSpaceEvent indicates an expected call of HandleUsedSpaceEvent.
|
||||||
func (mr *MockUserUsedSpaceSubscriberMockRecorder) name() *gomock.Call {
|
func (mr *MockUserUsedSpaceEventHandlerMockRecorder) HandleUsedSpaceEvent(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "name", reflect.TypeOf((*MockUserUsedSpaceSubscriber)(nil).name))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleUsedSpaceEvent", reflect.TypeOf((*MockUserUsedSpaceEventHandler)(nil).HandleUsedSpaceEvent), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,12 +57,7 @@ type Service struct {
|
|||||||
paused uint32
|
paused uint32
|
||||||
panicHandler async.PanicHandler
|
panicHandler async.PanicHandler
|
||||||
|
|
||||||
userSubscriberList userSubscriberList
|
subscriberList eventSubscriberList
|
||||||
addressSubscribers addressSubscriberList
|
|
||||||
labelSubscribers labelSubscriberList
|
|
||||||
messageSubscribers messageSubscriberList
|
|
||||||
refreshSubscribers refreshSubscriberList
|
|
||||||
userUsedSpaceSubscriber userUsedSpaceSubscriberList
|
|
||||||
|
|
||||||
pendingSubscriptionsLock sync.Mutex
|
pendingSubscriptionsLock sync.Mutex
|
||||||
pendingSubscriptions []pendingSubscription
|
pendingSubscriptions []pendingSubscription
|
||||||
@ -94,61 +89,9 @@ func NewService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Subscription struct {
|
|
||||||
User UserSubscriber
|
|
||||||
Refresh RefreshSubscriber
|
|
||||||
Address AddressSubscriber
|
|
||||||
Labels LabelSubscriber
|
|
||||||
Messages MessageSubscriber
|
|
||||||
UserUsedSpace UserUsedSpaceSubscriber
|
|
||||||
}
|
|
||||||
|
|
||||||
// cancel subscription subscribers if applicable, see `subscriber.cancel` for more information.
|
|
||||||
func (s Subscription) cancel() {
|
|
||||||
if s.User != nil {
|
|
||||||
s.User.cancel()
|
|
||||||
}
|
|
||||||
if s.Refresh != nil {
|
|
||||||
s.Refresh.cancel()
|
|
||||||
}
|
|
||||||
if s.Address != nil {
|
|
||||||
s.Address.cancel()
|
|
||||||
}
|
|
||||||
if s.Labels != nil {
|
|
||||||
s.Labels.cancel()
|
|
||||||
}
|
|
||||||
if s.Messages != nil {
|
|
||||||
s.Messages.cancel()
|
|
||||||
}
|
|
||||||
if s.UserUsedSpace != nil {
|
|
||||||
s.UserUsedSpace.cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Subscription) close() {
|
|
||||||
if s.User != nil {
|
|
||||||
s.User.close()
|
|
||||||
}
|
|
||||||
if s.Refresh != nil {
|
|
||||||
s.Refresh.close()
|
|
||||||
}
|
|
||||||
if s.Address != nil {
|
|
||||||
s.Address.close()
|
|
||||||
}
|
|
||||||
if s.Labels != nil {
|
|
||||||
s.Labels.close()
|
|
||||||
}
|
|
||||||
if s.Messages != nil {
|
|
||||||
s.Messages.close()
|
|
||||||
}
|
|
||||||
if s.UserUsedSpace != nil {
|
|
||||||
s.UserUsedSpace.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subscribe adds new subscribers to the service.
|
// Subscribe adds new subscribers to the service.
|
||||||
// This method can safely be called during event handling.
|
// This method can safely be called during event handling.
|
||||||
func (s *Service) Subscribe(subscription Subscription) {
|
func (s *Service) Subscribe(subscription EventSubscriber) {
|
||||||
s.pendingSubscriptionsLock.Lock()
|
s.pendingSubscriptionsLock.Lock()
|
||||||
defer s.pendingSubscriptionsLock.Unlock()
|
defer s.pendingSubscriptionsLock.Unlock()
|
||||||
|
|
||||||
@ -157,7 +100,7 @@ func (s *Service) Subscribe(subscription Subscription) {
|
|||||||
|
|
||||||
// Unsubscribe removes subscribers from the service.
|
// Unsubscribe removes subscribers from the service.
|
||||||
// This method can safely be called during event handling.
|
// This method can safely be called during event handling.
|
||||||
func (s *Service) Unsubscribe(subscription Subscription) {
|
func (s *Service) Unsubscribe(subscription EventSubscriber) {
|
||||||
subscription.cancel()
|
subscription.cancel()
|
||||||
|
|
||||||
s.pendingSubscriptionsLock.Lock()
|
s.pendingSubscriptionsLock.Lock()
|
||||||
@ -288,7 +231,7 @@ func (s *Service) Close() {
|
|||||||
s.pendingSubscriptionsLock.Lock()
|
s.pendingSubscriptionsLock.Lock()
|
||||||
defer s.pendingSubscriptionsLock.Unlock()
|
defer s.pendingSubscriptionsLock.Unlock()
|
||||||
|
|
||||||
processed := xmaps.Set[Subscription]{}
|
processed := xmaps.Set[EventSubscriber]{}
|
||||||
|
|
||||||
// Cleanup pending removes.
|
// Cleanup pending removes.
|
||||||
for _, s := range s.pendingSubscriptions {
|
for _, s := range s.pendingSubscriptions {
|
||||||
@ -313,70 +256,20 @@ func (s *Service) handleEvent(ctx context.Context, lastEventID string, event pro
|
|||||||
}).Info("Received new API event")
|
}).Info("Received new API event")
|
||||||
|
|
||||||
if event.Refresh&proton.RefreshMail != 0 {
|
if event.Refresh&proton.RefreshMail != 0 {
|
||||||
s.log.Info("Handling refresh event")
|
s.log.Info("Received refresh event")
|
||||||
if err := s.refreshSubscribers.Publish(ctx, event.Refresh, s.eventTimeout); err != nil {
|
|
||||||
return fmt.Errorf("failed to apply refresh event: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start with user events.
|
return s.subscriberList.PublishParallel(ctx, event, s.panicHandler, s.eventTimeout)
|
||||||
if event.User != nil {
|
|
||||||
if err := s.userSubscriberList.PublishParallel(ctx, *event.User, s.panicHandler, s.eventTimeout); err != nil {
|
|
||||||
return fmt.Errorf("failed to apply user event: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next Address events
|
|
||||||
if err := s.addressSubscribers.PublishParallel(ctx, event.Addresses, s.panicHandler, s.eventTimeout); err != nil {
|
|
||||||
return fmt.Errorf("failed to apply address events: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next label events
|
|
||||||
if err := s.labelSubscribers.PublishParallel(ctx, event.Labels, s.panicHandler, s.eventTimeout); err != nil {
|
|
||||||
return fmt.Errorf("failed to apply label events: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next message events
|
|
||||||
if err := s.messageSubscribers.PublishParallel(ctx, event.Messages, s.panicHandler, s.eventTimeout); err != nil {
|
|
||||||
return fmt.Errorf("failed to apply message events: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally user used space events
|
|
||||||
if event.UsedSpace != nil {
|
|
||||||
if err := s.userUsedSpaceSubscriber.PublishParallel(ctx, *event.UsedSpace, s.panicHandler, s.eventTimeout); err != nil {
|
|
||||||
return fmt.Errorf("failed to apply message events: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func unpackPublisherError(err error) (string, error) {
|
func unpackPublisherError(err error) (string, error) {
|
||||||
var addressErr *addressPublishError
|
var publishErr *eventPublishError
|
||||||
var labelErr *labelPublishError
|
|
||||||
var messageErr *messagePublishError
|
|
||||||
var refreshErr *refreshPublishError
|
|
||||||
var userErr *userPublishError
|
|
||||||
var usedSpaceErr *userUsedEventPublishError
|
|
||||||
|
|
||||||
switch {
|
if errors.As(err, &publishErr) {
|
||||||
case errors.As(err, &userErr):
|
return publishErr.subscriber.name(), publishErr.error
|
||||||
return userErr.subscriber.name(), userErr.error
|
|
||||||
case errors.As(err, &addressErr):
|
|
||||||
return addressErr.subscriber.name(), addressErr.error
|
|
||||||
case errors.As(err, &labelErr):
|
|
||||||
return labelErr.subscriber.name(), labelErr.error
|
|
||||||
case errors.As(err, &messageErr):
|
|
||||||
return messageErr.subscriber.name(), messageErr.error
|
|
||||||
case errors.As(err, &refreshErr):
|
|
||||||
return refreshErr.subscriber.name(), refreshErr.error
|
|
||||||
case errors.As(err, &usedSpaceErr):
|
|
||||||
return usedSpaceErr.subscriber.name(), usedSpaceErr.error
|
|
||||||
default:
|
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) handleEventError(ctx context.Context, lastEventID string, event proton.Event, err error) (string, error) {
|
func (s *Service) handleEventError(ctx context.Context, lastEventID string, event proton.Event, err error) (string, error) {
|
||||||
@ -437,56 +330,12 @@ func (s *Service) onBadEvent(ctx context.Context, event events.UserBadEvent) {
|
|||||||
s.eventPublisher.PublishEvent(ctx, event)
|
s.eventPublisher.PublishEvent(ctx, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) addSubscription(subscription Subscription) {
|
func (s *Service) addSubscription(subscription EventSubscriber) {
|
||||||
if subscription.User != nil {
|
s.subscriberList.Add(subscription)
|
||||||
s.userSubscriberList.Add(subscription.User)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscription.Refresh != nil {
|
|
||||||
s.refreshSubscribers.Add(subscription.Refresh)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscription.Address != nil {
|
|
||||||
s.addressSubscribers.Add(subscription.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscription.Labels != nil {
|
|
||||||
s.labelSubscribers.Add(subscription.Labels)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscription.Messages != nil {
|
|
||||||
s.messageSubscribers.Add(subscription.Messages)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscription.UserUsedSpace != nil {
|
|
||||||
s.userUsedSpaceSubscriber.Add(subscription.UserUsedSpace)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) removeSubscription(subscription Subscription) {
|
func (s *Service) removeSubscription(subscription EventSubscriber) {
|
||||||
if subscription.User != nil {
|
s.subscriberList.Remove(subscription)
|
||||||
s.userSubscriberList.Remove(subscription.User)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscription.Refresh != nil {
|
|
||||||
s.refreshSubscribers.Remove(subscription.Refresh)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscription.Address != nil {
|
|
||||||
s.addressSubscribers.Remove(subscription.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscription.Labels != nil {
|
|
||||||
s.labelSubscribers.Remove(subscription.Labels)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscription.Messages != nil {
|
|
||||||
s.messageSubscribers.Remove(subscription.Messages)
|
|
||||||
}
|
|
||||||
|
|
||||||
if subscription.UserUsedSpace != nil {
|
|
||||||
s.userUsedSpaceSubscriber.Remove(subscription.UserUsedSpace)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type pendingOp int
|
type pendingOp int
|
||||||
@ -498,5 +347,5 @@ const (
|
|||||||
|
|
||||||
type pendingSubscription struct {
|
type pendingSubscription struct {
|
||||||
op pendingOp
|
op pendingOp
|
||||||
sub Subscription
|
sub EventSubscriber
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,9 +52,9 @@ func TestServiceHandleEventError_SubscriberEventUnwrapping(t *testing.T) {
|
|||||||
|
|
||||||
lastEventID := "PrevEvent"
|
lastEventID := "PrevEvent"
|
||||||
event := proton.Event{EventID: "MyEvent"}
|
event := proton.Event{EventID: "MyEvent"}
|
||||||
subscriber := &noOpSubscriber[proton.AddressEvent]{}
|
subscriber := &noOpSubscriber[proton.Event]{}
|
||||||
|
|
||||||
err := &addressPublishError{
|
err := &eventPublishError{
|
||||||
subscriber: subscriber,
|
subscriber: subscriber,
|
||||||
error: &proton.NetError{},
|
error: &proton.NetError{},
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@ func (n noOpSubscriber[T]) name() string { //nolint:unused
|
|||||||
return "NoopSubscriber"
|
return "NoopSubscriber"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n noOpSubscriber[T]) handle(_ context.Context, _ []T) error { //nolint:unused
|
func (n noOpSubscriber[T]) handle(_ context.Context, _ T) error { //nolint:unused
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,26 +37,26 @@ func TestServiceHandleEvent_CheckEventCategoriesHandledInOrder(t *testing.T) {
|
|||||||
eventPublisher := mocks.NewMockEventPublisher(mockCtrl)
|
eventPublisher := mocks.NewMockEventPublisher(mockCtrl)
|
||||||
eventIDStore := NewInMemoryEventIDStore()
|
eventIDStore := NewInMemoryEventIDStore()
|
||||||
|
|
||||||
refreshHandler := NewMockRefreshSubscriber(mockCtrl)
|
refreshHandler := NewMockRefreshEventHandler(mockCtrl)
|
||||||
refreshHandler.EXPECT().handle(gomock.Any(), gomock.Any()).Times(2).Return(nil)
|
refreshHandler.EXPECT().HandleRefreshEvent(gomock.Any(), gomock.Any()).Times(2).Return(nil)
|
||||||
|
|
||||||
userHandler := NewMockUserSubscriber(mockCtrl)
|
userHandler := NewMockUserEventHandler(mockCtrl)
|
||||||
userCall := userHandler.EXPECT().handle(gomock.Any(), gomock.Any()).Times(1).Return(nil)
|
userCall := userHandler.EXPECT().HandleUserEvent(gomock.Any(), gomock.Any()).Times(1).Return(nil)
|
||||||
|
|
||||||
addressHandler := NewMockAddressSubscriber(mockCtrl)
|
addressHandler := NewMockAddressEventHandler(mockCtrl)
|
||||||
addressCall := addressHandler.EXPECT().handle(gomock.Any(), gomock.Any()).After(userCall).Times(1).Return(nil)
|
addressCall := addressHandler.EXPECT().HandleAddressEvents(gomock.Any(), gomock.Any()).After(userCall).Times(1).Return(nil)
|
||||||
|
|
||||||
labelHandler := NewMockLabelSubscriber(mockCtrl)
|
labelHandler := NewMockLabelEventHandler(mockCtrl)
|
||||||
labelCall := labelHandler.EXPECT().handle(gomock.Any(), gomock.Any()).After(addressCall).Times(1).Return(nil)
|
labelCall := labelHandler.EXPECT().HandleLabelEvents(gomock.Any(), gomock.Any()).After(addressCall).Times(1).Return(nil)
|
||||||
|
|
||||||
messageHandler := NewMockMessageSubscriber(mockCtrl)
|
messageHandler := NewMockMessageEventHandler(mockCtrl)
|
||||||
messageCall := messageHandler.EXPECT().handle(gomock.Any(), gomock.Any()).After(labelCall).Times(1).Return(nil)
|
messageCall := messageHandler.EXPECT().HandleMessageEvents(gomock.Any(), gomock.Any()).After(labelCall).Times(1).Return(nil)
|
||||||
|
|
||||||
userSpaceHandler := NewMockUserUsedSpaceSubscriber(mockCtrl)
|
userSpaceHandler := NewMockUserUsedSpaceEventHandler(mockCtrl)
|
||||||
userSpaceCall := userSpaceHandler.EXPECT().handle(gomock.Any(), gomock.Any()).After(messageCall).Times(1).Return(nil)
|
userSpaceCall := userSpaceHandler.EXPECT().HandleUsedSpaceEvent(gomock.Any(), gomock.Any()).After(messageCall).Times(1).Return(nil)
|
||||||
|
|
||||||
secondRefreshHandler := NewMockRefreshSubscriber(mockCtrl)
|
secondRefreshHandler := NewMockRefreshEventHandler(mockCtrl)
|
||||||
secondRefreshHandler.EXPECT().handle(gomock.Any(), gomock.Any()).After(userSpaceCall).Times(1).Return(nil)
|
secondRefreshHandler.EXPECT().HandleRefreshEvent(gomock.Any(), gomock.Any()).After(userSpaceCall).Times(1).Return(nil)
|
||||||
|
|
||||||
service := NewService(
|
service := NewService(
|
||||||
"foo",
|
"foo",
|
||||||
@ -65,27 +65,31 @@ func TestServiceHandleEvent_CheckEventCategoriesHandledInOrder(t *testing.T) {
|
|||||||
eventPublisher,
|
eventPublisher,
|
||||||
100*time.Millisecond,
|
100*time.Millisecond,
|
||||||
time.Millisecond,
|
time.Millisecond,
|
||||||
time.Second,
|
10*time.Second,
|
||||||
async.NoopPanicHandler{},
|
async.NoopPanicHandler{},
|
||||||
)
|
)
|
||||||
|
|
||||||
service.addSubscription(Subscription{
|
subscription := NewCallbackSubscriber("test", EventHandler{
|
||||||
User: userHandler,
|
UserHandler: userHandler,
|
||||||
Refresh: refreshHandler,
|
RefreshHandler: refreshHandler,
|
||||||
Address: addressHandler,
|
AddressHandler: addressHandler,
|
||||||
Labels: labelHandler,
|
LabelHandler: labelHandler,
|
||||||
Messages: messageHandler,
|
MessageHandler: messageHandler,
|
||||||
UserUsedSpace: userSpaceHandler,
|
UsedSpaceHandler: userSpaceHandler,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
service.addSubscription(subscription)
|
||||||
|
|
||||||
// Simulate 1st refresh.
|
// Simulate 1st refresh.
|
||||||
require.NoError(t, service.handleEvent(context.Background(), "", proton.Event{Refresh: proton.RefreshMail}))
|
require.NoError(t, service.handleEvent(context.Background(), "", proton.Event{Refresh: proton.RefreshMail}))
|
||||||
|
|
||||||
// Simulate Regular event.
|
// Simulate Regular event.
|
||||||
usedSpace := 20
|
usedSpace := 20
|
||||||
require.NoError(t, service.handleEvent(context.Background(), "", proton.Event{
|
require.NoError(t, service.handleEvent(context.Background(), "", proton.Event{
|
||||||
User: new(proton.User),
|
User: new(proton.User),
|
||||||
Addresses: []proton.AddressEvent{},
|
Addresses: []proton.AddressEvent{
|
||||||
|
{},
|
||||||
|
},
|
||||||
Labels: []proton.LabelEvent{
|
Labels: []proton.LabelEvent{
|
||||||
{},
|
{},
|
||||||
},
|
},
|
||||||
@ -95,9 +99,9 @@ func TestServiceHandleEvent_CheckEventCategoriesHandledInOrder(t *testing.T) {
|
|||||||
UsedSpace: &usedSpace,
|
UsedSpace: &usedSpace,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
service.addSubscription(Subscription{
|
service.addSubscription(NewCallbackSubscriber("test", EventHandler{
|
||||||
Refresh: secondRefreshHandler,
|
RefreshHandler: secondRefreshHandler,
|
||||||
})
|
}))
|
||||||
|
|
||||||
// Simulate 2nd refresh.
|
// Simulate 2nd refresh.
|
||||||
require.NoError(t, service.handleEvent(context.Background(), "", proton.Event{Refresh: proton.RefreshMail}))
|
require.NoError(t, service.handleEvent(context.Background(), "", proton.Event{Refresh: proton.RefreshMail}))
|
||||||
@ -109,11 +113,10 @@ func TestServiceHandleEvent_CheckEventFailureCausesError(t *testing.T) {
|
|||||||
eventPublisher := mocks.NewMockEventPublisher(mockCtrl)
|
eventPublisher := mocks.NewMockEventPublisher(mockCtrl)
|
||||||
eventIDStore := NewInMemoryEventIDStore()
|
eventIDStore := NewInMemoryEventIDStore()
|
||||||
|
|
||||||
addressHandler := NewMockAddressSubscriber(mockCtrl)
|
addressHandler := NewMockAddressEventHandler(mockCtrl)
|
||||||
addressHandler.EXPECT().name().MinTimes(1).Return("Hello")
|
addressHandler.EXPECT().HandleAddressEvents(gomock.Any(), gomock.Any()).Times(1).Return(fmt.Errorf("failed"))
|
||||||
addressHandler.EXPECT().handle(gomock.Any(), gomock.Any()).Times(1).Return(fmt.Errorf("failed"))
|
|
||||||
|
|
||||||
messageHandler := NewMockMessageSubscriber(mockCtrl)
|
messageHandler := NewMockMessageEventHandler(mockCtrl)
|
||||||
|
|
||||||
service := NewService(
|
service := NewService(
|
||||||
"foo",
|
"foo",
|
||||||
@ -126,16 +129,18 @@ func TestServiceHandleEvent_CheckEventFailureCausesError(t *testing.T) {
|
|||||||
async.NoopPanicHandler{},
|
async.NoopPanicHandler{},
|
||||||
)
|
)
|
||||||
|
|
||||||
service.addSubscription(Subscription{
|
subscription := NewCallbackSubscriber("test", EventHandler{
|
||||||
Address: addressHandler,
|
AddressHandler: addressHandler,
|
||||||
Messages: messageHandler,
|
MessageHandler: messageHandler,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
service.addSubscription(subscription)
|
||||||
|
|
||||||
err := service.handleEvent(context.Background(), "", proton.Event{Addresses: []proton.AddressEvent{{}}})
|
err := service.handleEvent(context.Background(), "", proton.Event{Addresses: []proton.AddressEvent{{}}})
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
publisherErr := new(addressPublishError)
|
publisherErr := new(eventPublishError)
|
||||||
require.True(t, errors.As(err, &publisherErr))
|
require.True(t, errors.As(err, &publisherErr))
|
||||||
require.Equal(t, publisherErr.subscriber, addressHandler)
|
require.Equal(t, publisherErr.subscriber, subscription)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceHandleEvent_CheckEventFailureCausesErrorParallel(t *testing.T) {
|
func TestServiceHandleEvent_CheckEventFailureCausesErrorParallel(t *testing.T) {
|
||||||
@ -144,12 +149,11 @@ func TestServiceHandleEvent_CheckEventFailureCausesErrorParallel(t *testing.T) {
|
|||||||
eventPublisher := mocks.NewMockEventPublisher(mockCtrl)
|
eventPublisher := mocks.NewMockEventPublisher(mockCtrl)
|
||||||
eventIDStore := NewInMemoryEventIDStore()
|
eventIDStore := NewInMemoryEventIDStore()
|
||||||
|
|
||||||
addressHandler := NewMockAddressSubscriber(mockCtrl)
|
addressHandler := NewMockAddressEventHandler(mockCtrl)
|
||||||
addressHandler.EXPECT().name().MinTimes(1).Return("Hello")
|
addressHandler.EXPECT().HandleAddressEvents(gomock.Any(), gomock.Any()).Times(1).Return(fmt.Errorf("failed"))
|
||||||
addressHandler.EXPECT().handle(gomock.Any(), gomock.Any()).Times(1).Return(fmt.Errorf("failed"))
|
|
||||||
|
|
||||||
addressHandler2 := NewMockAddressSubscriber(mockCtrl)
|
addressHandler2 := NewMockAddressEventHandler(mockCtrl)
|
||||||
addressHandler2.EXPECT().handle(gomock.Any(), gomock.Any()).MaxTimes(1).Return(nil)
|
addressHandler2.EXPECT().HandleAddressEvents(gomock.Any(), gomock.Any()).MaxTimes(1).Return(nil)
|
||||||
|
|
||||||
service := NewService(
|
service := NewService(
|
||||||
"foo",
|
"foo",
|
||||||
@ -162,19 +166,21 @@ func TestServiceHandleEvent_CheckEventFailureCausesErrorParallel(t *testing.T) {
|
|||||||
async.NoopPanicHandler{},
|
async.NoopPanicHandler{},
|
||||||
)
|
)
|
||||||
|
|
||||||
service.addSubscription(Subscription{
|
subscription := NewCallbackSubscriber("test", EventHandler{
|
||||||
Address: addressHandler,
|
AddressHandler: addressHandler,
|
||||||
})
|
})
|
||||||
|
|
||||||
service.addSubscription(Subscription{
|
service.addSubscription(subscription)
|
||||||
Address: addressHandler2,
|
|
||||||
})
|
service.addSubscription(NewCallbackSubscriber("test2", EventHandler{
|
||||||
|
AddressHandler: addressHandler2,
|
||||||
|
}))
|
||||||
|
|
||||||
err := service.handleEvent(context.Background(), "", proton.Event{Addresses: []proton.AddressEvent{{}}})
|
err := service.handleEvent(context.Background(), "", proton.Event{Addresses: []proton.AddressEvent{{}}})
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
publisherErr := new(addressPublishError)
|
publisherErr := new(eventPublishError)
|
||||||
require.True(t, errors.As(err, &publisherErr))
|
require.True(t, errors.As(err, &publisherErr))
|
||||||
require.Equal(t, publisherErr.subscriber, addressHandler)
|
require.Equal(t, publisherErr.subscriber, subscription)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceHandleEvent_SubscriberTimeout(t *testing.T) {
|
func TestServiceHandleEvent_SubscriberTimeout(t *testing.T) {
|
||||||
@ -183,13 +189,11 @@ func TestServiceHandleEvent_SubscriberTimeout(t *testing.T) {
|
|||||||
eventPublisher := mocks.NewMockEventPublisher(mockCtrl)
|
eventPublisher := mocks.NewMockEventPublisher(mockCtrl)
|
||||||
eventIDStore := NewInMemoryEventIDStore()
|
eventIDStore := NewInMemoryEventIDStore()
|
||||||
|
|
||||||
addressHandler := NewMockAddressSubscriber(mockCtrl)
|
addressHandler := NewMockAddressEventHandler(mockCtrl)
|
||||||
addressHandler.EXPECT().name().AnyTimes().Return("Ok")
|
addressHandler.EXPECT().HandleAddressEvents(gomock.Any(), gomock.Any()).MaxTimes(1).Return(nil)
|
||||||
addressHandler.EXPECT().handle(gomock.Any(), gomock.Any()).MaxTimes(1).Return(nil)
|
|
||||||
|
|
||||||
addressHandler2 := NewMockAddressSubscriber(mockCtrl)
|
addressHandler2 := NewMockAddressEventHandler(mockCtrl)
|
||||||
addressHandler2.EXPECT().name().AnyTimes().Return("Timeout")
|
addressHandler2.EXPECT().HandleAddressEvents(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, _ []proton.AddressEvent) error {
|
||||||
addressHandler2.EXPECT().handle(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, _ []proton.AddressEvent) error {
|
|
||||||
timer := time.NewTimer(time.Second)
|
timer := time.NewTimer(time.Second)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@ -211,19 +215,21 @@ func TestServiceHandleEvent_SubscriberTimeout(t *testing.T) {
|
|||||||
async.NoopPanicHandler{},
|
async.NoopPanicHandler{},
|
||||||
)
|
)
|
||||||
|
|
||||||
service.addSubscription(Subscription{
|
subscription := NewCallbackSubscriber("test", EventHandler{
|
||||||
Address: addressHandler,
|
AddressHandler: addressHandler2,
|
||||||
})
|
})
|
||||||
|
|
||||||
service.addSubscription(Subscription{
|
service.addSubscription(subscription)
|
||||||
Address: addressHandler2,
|
|
||||||
})
|
service.addSubscription(NewCallbackSubscriber("test2", EventHandler{
|
||||||
|
AddressHandler: addressHandler,
|
||||||
|
}))
|
||||||
|
|
||||||
// Simulate 1st refresh.
|
// Simulate 1st refresh.
|
||||||
err := service.handleEvent(context.Background(), "", proton.Event{Addresses: []proton.AddressEvent{{}}})
|
err := service.handleEvent(context.Background(), "", proton.Event{Addresses: []proton.AddressEvent{{}}})
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
if publisherErr := new(addressPublishError); errors.As(err, &publisherErr) {
|
if publisherErr := new(eventPublishError); errors.As(err, &publisherErr) {
|
||||||
require.Equal(t, publisherErr.subscriber, addressHandler)
|
require.Equal(t, publisherErr.subscriber, subscription)
|
||||||
require.True(t, errors.Is(publisherErr.error, ErrPublishTimeoutExceeded))
|
require.True(t, errors.Is(publisherErr.error, ErrPublishTimeoutExceeded))
|
||||||
} else {
|
} else {
|
||||||
require.True(t, errors.Is(err, ErrPublishTimeoutExceeded))
|
require.True(t, errors.Is(err, ErrPublishTimeoutExceeded))
|
||||||
|
|||||||
@ -87,7 +87,7 @@ func TestService_RetryEventOnNonCatastrophicFailure(t *testing.T) {
|
|||||||
eventPublisher := mocks2.NewMockEventPublisher(mockCtrl)
|
eventPublisher := mocks2.NewMockEventPublisher(mockCtrl)
|
||||||
eventIDStore := mocks.NewMockEventIDStore(mockCtrl)
|
eventIDStore := mocks.NewMockEventIDStore(mockCtrl)
|
||||||
eventSource := mocks.NewMockEventSource(mockCtrl)
|
eventSource := mocks.NewMockEventSource(mockCtrl)
|
||||||
subscriber := NewMockMessageSubscriber(mockCtrl)
|
subscriber := NewMockMessageEventHandler(mockCtrl)
|
||||||
|
|
||||||
firstEventID := "EVENT01"
|
firstEventID := "EVENT01"
|
||||||
secondEventID := "EVENT02"
|
secondEventID := "EVENT02"
|
||||||
@ -113,10 +113,9 @@ func TestService_RetryEventOnNonCatastrophicFailure(t *testing.T) {
|
|||||||
eventSource.EXPECT().GetEvent(gomock.Any(), gomock.Eq(firstEventID)).MinTimes(1).Return(secondEvent, false, nil)
|
eventSource.EXPECT().GetEvent(gomock.Any(), gomock.Eq(firstEventID)).MinTimes(1).Return(secondEvent, false, nil)
|
||||||
|
|
||||||
// Subscriber expectations.
|
// Subscriber expectations.
|
||||||
subscriber.EXPECT().name().AnyTimes().Return("Foo")
|
|
||||||
{
|
{
|
||||||
firstCall := subscriber.EXPECT().handle(gomock.Any(), gomock.Eq(messageEvents)).Times(1).Return(io.ErrUnexpectedEOF)
|
firstCall := subscriber.EXPECT().HandleMessageEvents(gomock.Any(), gomock.Eq(messageEvents)).Times(1).Return(io.ErrUnexpectedEOF)
|
||||||
subscriber.EXPECT().handle(gomock.Any(), gomock.Eq(messageEvents)).After(firstCall).Times(1).Return(nil)
|
subscriber.EXPECT().HandleMessageEvents(gomock.Any(), gomock.Eq(messageEvents)).After(firstCall).Times(1).Return(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
service := NewService(
|
service := NewService(
|
||||||
@ -129,7 +128,7 @@ func TestService_RetryEventOnNonCatastrophicFailure(t *testing.T) {
|
|||||||
time.Second,
|
time.Second,
|
||||||
async.NoopPanicHandler{},
|
async.NoopPanicHandler{},
|
||||||
)
|
)
|
||||||
service.Subscribe(Subscription{Messages: subscriber})
|
service.Subscribe(NewCallbackSubscriber("foo", EventHandler{MessageHandler: subscriber}))
|
||||||
|
|
||||||
require.NoError(t, service.Start(context.Background(), group))
|
require.NoError(t, service.Start(context.Background(), group))
|
||||||
service.Resume()
|
service.Resume()
|
||||||
@ -142,7 +141,7 @@ func TestService_OnBadEventServiceIsPaused(t *testing.T) {
|
|||||||
eventPublisher := mocks2.NewMockEventPublisher(mockCtrl)
|
eventPublisher := mocks2.NewMockEventPublisher(mockCtrl)
|
||||||
eventIDStore := mocks.NewMockEventIDStore(mockCtrl)
|
eventIDStore := mocks.NewMockEventIDStore(mockCtrl)
|
||||||
eventSource := mocks.NewMockEventSource(mockCtrl)
|
eventSource := mocks.NewMockEventSource(mockCtrl)
|
||||||
subscriber := NewMockMessageSubscriber(mockCtrl)
|
subscriber := NewMockMessageEventHandler(mockCtrl)
|
||||||
|
|
||||||
firstEventID := "EVENT01"
|
firstEventID := "EVENT01"
|
||||||
secondEventID := "EVENT02"
|
secondEventID := "EVENT02"
|
||||||
@ -164,8 +163,7 @@ func TestService_OnBadEventServiceIsPaused(t *testing.T) {
|
|||||||
|
|
||||||
// Subscriber expectations.
|
// Subscriber expectations.
|
||||||
badEventErr := fmt.Errorf("I will cause bad event")
|
badEventErr := fmt.Errorf("I will cause bad event")
|
||||||
subscriber.EXPECT().name().AnyTimes().Return("Foo")
|
subscriber.EXPECT().HandleMessageEvents(gomock.Any(), gomock.Eq(messageEvents)).Times(1).Return(badEventErr)
|
||||||
subscriber.EXPECT().handle(gomock.Any(), gomock.Eq(messageEvents)).Times(1).Return(badEventErr)
|
|
||||||
|
|
||||||
service := NewService(
|
service := NewService(
|
||||||
"foo",
|
"foo",
|
||||||
@ -184,7 +182,7 @@ func TestService_OnBadEventServiceIsPaused(t *testing.T) {
|
|||||||
OldEventID: firstEventID,
|
OldEventID: firstEventID,
|
||||||
NewEventID: secondEventID,
|
NewEventID: secondEventID,
|
||||||
EventInfo: secondEvent[0].String(),
|
EventInfo: secondEvent[0].String(),
|
||||||
Error: badEventErr,
|
Error: fmt.Errorf("failed to apply message events: %w", badEventErr),
|
||||||
}).Do(func(_ context.Context, event events.Event) {
|
}).Do(func(_ context.Context, event events.Event) {
|
||||||
group.Go(context.Background(), "", "", func(_ context.Context) {
|
group.Go(context.Background(), "", "", func(_ context.Context) {
|
||||||
// Use background context to avoid having the request cancelled
|
// Use background context to avoid having the request cancelled
|
||||||
@ -193,7 +191,7 @@ func TestService_OnBadEventServiceIsPaused(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
service.Subscribe(Subscription{Messages: subscriber})
|
service.Subscribe(NewCallbackSubscriber("foo", EventHandler{MessageHandler: subscriber}))
|
||||||
require.NoError(t, service.Start(context.Background(), group))
|
require.NoError(t, service.Start(context.Background(), group))
|
||||||
service.Resume()
|
service.Resume()
|
||||||
group.Wait()
|
group.Wait()
|
||||||
@ -205,7 +203,7 @@ func TestService_UnsubscribeDuringEventHandlingDoesNotCauseDeadlock(t *testing.T
|
|||||||
eventPublisher := mocks2.NewMockEventPublisher(mockCtrl)
|
eventPublisher := mocks2.NewMockEventPublisher(mockCtrl)
|
||||||
eventIDStore := mocks.NewMockEventIDStore(mockCtrl)
|
eventIDStore := mocks.NewMockEventIDStore(mockCtrl)
|
||||||
eventSource := mocks.NewMockEventSource(mockCtrl)
|
eventSource := mocks.NewMockEventSource(mockCtrl)
|
||||||
subscriber := NewMockMessageSubscriber(mockCtrl)
|
subscriber := NewMockMessageEventHandler(mockCtrl)
|
||||||
|
|
||||||
firstEventID := "EVENT01"
|
firstEventID := "EVENT01"
|
||||||
secondEventID := "EVENT02"
|
secondEventID := "EVENT02"
|
||||||
@ -241,16 +239,15 @@ func TestService_UnsubscribeDuringEventHandlingDoesNotCauseDeadlock(t *testing.T
|
|||||||
async.NoopPanicHandler{},
|
async.NoopPanicHandler{},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
subscription := NewCallbackSubscriber("foo", EventHandler{MessageHandler: subscriber})
|
||||||
|
|
||||||
// Subscriber expectations.
|
// Subscriber expectations.
|
||||||
subscriber.EXPECT().name().AnyTimes().Return("Foo")
|
subscriber.EXPECT().HandleMessageEvents(gomock.Any(), gomock.Eq(messageEvents)).Times(1).DoAndReturn(func(_ context.Context, _ []proton.MessageEvent) error {
|
||||||
subscriber.EXPECT().cancel().Times(1)
|
service.Unsubscribe(subscription)
|
||||||
subscriber.EXPECT().close().Times(1)
|
|
||||||
subscriber.EXPECT().handle(gomock.Any(), gomock.Eq(messageEvents)).Times(1).DoAndReturn(func(_ context.Context, _ []proton.MessageEvent) error {
|
|
||||||
service.Unsubscribe(Subscription{Messages: subscriber})
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
service.Subscribe(Subscription{Messages: subscriber})
|
service.Subscribe(subscription)
|
||||||
require.NoError(t, service.Start(context.Background(), group))
|
require.NoError(t, service.Start(context.Background(), group))
|
||||||
service.Resume()
|
service.Resume()
|
||||||
group.Wait()
|
group.Wait()
|
||||||
@ -262,7 +259,6 @@ func TestService_UnsubscribeBeforeHandlingEventIsNotConsideredError(t *testing.T
|
|||||||
eventPublisher := mocks2.NewMockEventPublisher(mockCtrl)
|
eventPublisher := mocks2.NewMockEventPublisher(mockCtrl)
|
||||||
eventIDStore := mocks.NewMockEventIDStore(mockCtrl)
|
eventIDStore := mocks.NewMockEventIDStore(mockCtrl)
|
||||||
eventSource := mocks.NewMockEventSource(mockCtrl)
|
eventSource := mocks.NewMockEventSource(mockCtrl)
|
||||||
subscriber := NewMessageSubscriber("My subscriber")
|
|
||||||
|
|
||||||
firstEventID := "EVENT01"
|
firstEventID := "EVENT01"
|
||||||
secondEventID := "EVENT02"
|
secondEventID := "EVENT02"
|
||||||
@ -299,16 +295,42 @@ func TestService_UnsubscribeBeforeHandlingEventIsNotConsideredError(t *testing.T
|
|||||||
async.NoopPanicHandler{},
|
async.NoopPanicHandler{},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
subscription := NewEventSubscriber("Foo")
|
||||||
|
|
||||||
// start subscriber
|
// start subscriber
|
||||||
group.Go(context.Background(), "", "", func(_ context.Context) {
|
group.Go(context.Background(), "", "", func(_ context.Context) {
|
||||||
defer service.Unsubscribe(Subscription{Messages: subscriber})
|
defer service.Unsubscribe(subscription)
|
||||||
|
|
||||||
// Simulate the reception of an event, but it is never handled due to unexpected exit
|
// Simulate the reception of an event, but it is never handled due to unexpected exit
|
||||||
<-time.NewTicker(500 * time.Millisecond).C
|
<-time.NewTicker(500 * time.Millisecond).C
|
||||||
})
|
})
|
||||||
|
|
||||||
service.Subscribe(Subscription{Messages: subscriber})
|
service.Subscribe(subscription)
|
||||||
require.NoError(t, service.Start(context.Background(), group))
|
require.NoError(t, service.Start(context.Background(), group))
|
||||||
service.Resume()
|
service.Resume()
|
||||||
group.Wait()
|
group.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CallbackSubscriber struct {
|
||||||
|
handler EventHandler
|
||||||
|
n string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCallbackSubscriber(name string, handler EventHandler) *CallbackSubscriber {
|
||||||
|
return &CallbackSubscriber{handler: handler, n: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CallbackSubscriber) name() string { //nolint: unused
|
||||||
|
return c.n
|
||||||
|
}
|
||||||
|
func (c CallbackSubscriber) handle(ctx context.Context, t proton.Event) error { //nolint: unused
|
||||||
|
return c.handler.OnEvent(ctx, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CallbackSubscriber) cancel() { //nolint: unused
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CallbackSubscriber) close() { //nolint: unused
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|||||||
@ -19,16 +19,16 @@ package userevents
|
|||||||
|
|
||||||
// Subscribable represents a type that allows the registration of event subscribers.
|
// Subscribable represents a type that allows the registration of event subscribers.
|
||||||
type Subscribable interface {
|
type Subscribable interface {
|
||||||
Subscribe(subscription Subscription)
|
Subscribe(subscription EventSubscriber)
|
||||||
Unsubscribe(subscription Subscription)
|
Unsubscribe(subscription EventSubscriber)
|
||||||
}
|
}
|
||||||
|
|
||||||
type NoOpSubscribable struct{}
|
type NoOpSubscribable struct{}
|
||||||
|
|
||||||
func (n NoOpSubscribable) Subscribe(_ Subscription) {
|
func (n NoOpSubscribable) Subscribe(_ EventSubscriber) {
|
||||||
// Does nothing
|
// Does nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n NoOpSubscribable) Unsubscribe(_ Subscription) {
|
func (n NoOpSubscribable) Unsubscribe(_ EventSubscriber) {
|
||||||
// Does nothing
|
// Does nothing
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,43 +31,13 @@ import (
|
|||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AddressChanneledSubscriber = ChanneledSubscriber[[]proton.AddressEvent]
|
type EventChanneledSubscriber = ChanneledSubscriber[proton.Event]
|
||||||
type LabelChanneledSubscriber = ChanneledSubscriber[[]proton.LabelEvent]
|
|
||||||
type MessageChanneledSubscriber = ChanneledSubscriber[[]proton.MessageEvent]
|
|
||||||
type UserChanneledSubscriber = ChanneledSubscriber[proton.User]
|
|
||||||
type RefreshChanneledSubscriber = ChanneledSubscriber[proton.RefreshFlag]
|
|
||||||
type UserUsedSpaceChanneledSubscriber = ChanneledSubscriber[int]
|
|
||||||
|
|
||||||
func NewMessageSubscriber(name string) *MessageChanneledSubscriber {
|
func newSubscriber(name string) *EventChanneledSubscriber {
|
||||||
return newChanneledSubscriber[[]proton.MessageEvent](name)
|
return newChanneledSubscriber[proton.Event](name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAddressSubscriber(name string) *AddressChanneledSubscriber {
|
type EventSubscriber = subscriber[proton.Event]
|
||||||
return newChanneledSubscriber[[]proton.AddressEvent](name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewLabelSubscriber(name string) *LabelChanneledSubscriber {
|
|
||||||
return newChanneledSubscriber[[]proton.LabelEvent](name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRefreshSubscriber(name string) *RefreshChanneledSubscriber {
|
|
||||||
return newChanneledSubscriber[proton.RefreshFlag](name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUserSubscriber(name string) *UserChanneledSubscriber {
|
|
||||||
return newChanneledSubscriber[proton.User](name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUserUsedSpaceSubscriber(name string) *UserUsedSpaceChanneledSubscriber {
|
|
||||||
return newChanneledSubscriber[int](name)
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddressSubscriber = subscriber[[]proton.AddressEvent]
|
|
||||||
type LabelSubscriber = subscriber[[]proton.LabelEvent]
|
|
||||||
type MessageSubscriber = subscriber[[]proton.MessageEvent]
|
|
||||||
type RefreshSubscriber = subscriber[proton.RefreshFlag]
|
|
||||||
type UserSubscriber = subscriber[proton.User]
|
|
||||||
type UserUsedSpaceSubscriber = subscriber[int]
|
|
||||||
|
|
||||||
// Subscriber is the main entry point of interacting with user generated events.
|
// Subscriber is the main entry point of interacting with user generated events.
|
||||||
type subscriber[T any] interface {
|
type subscriber[T any] interface {
|
||||||
@ -87,12 +57,7 @@ type subscriberList[T any] struct {
|
|||||||
subscribers []subscriber[T]
|
subscribers []subscriber[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
type addressSubscriberList = subscriberList[[]proton.AddressEvent]
|
type eventSubscriberList = subscriberList[proton.Event]
|
||||||
type labelSubscriberList = subscriberList[[]proton.LabelEvent]
|
|
||||||
type messageSubscriberList = subscriberList[[]proton.MessageEvent]
|
|
||||||
type refreshSubscriberList = subscriberList[proton.RefreshFlag]
|
|
||||||
type userSubscriberList = subscriberList[proton.User]
|
|
||||||
type userUsedSpaceSubscriberList = subscriberList[int]
|
|
||||||
|
|
||||||
func (s *subscriberList[T]) Add(subscriber subscriber[T]) {
|
func (s *subscriberList[T]) Add(subscriber subscriber[T]) {
|
||||||
if !slices.Contains(s.subscribers, subscriber) {
|
if !slices.Contains(s.subscribers, subscriber) {
|
||||||
@ -117,12 +82,7 @@ type publishError[T any] struct {
|
|||||||
|
|
||||||
var ErrPublishTimeoutExceeded = errors.New("event publish timed out")
|
var ErrPublishTimeoutExceeded = errors.New("event publish timed out")
|
||||||
|
|
||||||
type addressPublishError = publishError[[]proton.AddressEvent]
|
type eventPublishError = publishError[proton.Event]
|
||||||
type labelPublishError = publishError[[]proton.LabelEvent]
|
|
||||||
type messagePublishError = publishError[[]proton.MessageEvent]
|
|
||||||
type refreshPublishError = publishError[proton.RefreshFlag]
|
|
||||||
type userPublishError = publishError[proton.User]
|
|
||||||
type userUsedEventPublishError = publishError[int]
|
|
||||||
|
|
||||||
func (p publishError[T]) Error() string {
|
func (p publishError[T]) Error() string {
|
||||||
return fmt.Sprintf("Event publish failed on (%v): %v", p.subscriber.name(), p.error.Error())
|
return fmt.Sprintf("Event publish failed on (%v): %v", p.subscriber.name(), p.error.Error())
|
||||||
|
|||||||
106
internal/services/userevents/subscription.go
Normal file
106
internal/services/userevents/subscription.go
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// Copyright (c) 2023 Proton AG
|
||||||
|
//
|
||||||
|
// This file is part of Proton Mail Bridge.
|
||||||
|
//
|
||||||
|
// Proton Mail Bridge is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Proton Mail Bridge is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package userevents
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ProtonMail/go-proton-api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Subscription = EventSubscriber
|
||||||
|
|
||||||
|
func NewEventSubscriber(name string) *EventChanneledSubscriber {
|
||||||
|
return newSubscriber(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventHandler struct {
|
||||||
|
RefreshHandler RefreshEventHandler
|
||||||
|
AddressHandler AddressEventHandler
|
||||||
|
UserHandler UserEventHandler
|
||||||
|
LabelHandler LabelEventHandler
|
||||||
|
MessageHandler MessageEventHandler
|
||||||
|
UsedSpaceHandler UserUsedSpaceEventHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EventHandler) OnEvent(ctx context.Context, event proton.Event) error {
|
||||||
|
if event.Refresh&proton.RefreshMail != 0 && e.RefreshHandler != nil {
|
||||||
|
return e.RefreshHandler.HandleRefreshEvent(ctx, event.Refresh)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start with user events.
|
||||||
|
if event.User != nil && e.UserHandler != nil {
|
||||||
|
if err := e.UserHandler.HandleUserEvent(ctx, event.User); err != nil {
|
||||||
|
return fmt.Errorf("failed to apply user event: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next Address events
|
||||||
|
if len(event.Addresses) != 0 && e.AddressHandler != nil {
|
||||||
|
if err := e.AddressHandler.HandleAddressEvents(ctx, event.Addresses); err != nil {
|
||||||
|
return fmt.Errorf("failed to apply address events: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next label events
|
||||||
|
if len(event.Labels) != 0 && e.LabelHandler != nil {
|
||||||
|
if err := e.LabelHandler.HandleLabelEvents(ctx, event.Labels); err != nil {
|
||||||
|
return fmt.Errorf("failed to apply label events: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next message events
|
||||||
|
if len(event.Messages) != 0 && e.MessageHandler != nil {
|
||||||
|
if err := e.MessageHandler.HandleMessageEvents(ctx, event.Messages); err != nil {
|
||||||
|
return fmt.Errorf("failed to apply message events: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally user used space events
|
||||||
|
if event.UsedSpace != nil && e.UsedSpaceHandler != nil {
|
||||||
|
if err := e.UsedSpaceHandler.HandleUsedSpaceEvent(ctx, *event.UsedSpace); err != nil {
|
||||||
|
return fmt.Errorf("failed to apply message events: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type RefreshEventHandler interface {
|
||||||
|
HandleRefreshEvent(ctx context.Context, flag proton.RefreshFlag) error
|
||||||
|
}
|
||||||
|
type UserEventHandler interface {
|
||||||
|
HandleUserEvent(ctx context.Context, user *proton.User) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserUsedSpaceEventHandler interface {
|
||||||
|
HandleUsedSpaceEvent(ctx context.Context, newSpace int) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type AddressEventHandler interface {
|
||||||
|
HandleAddressEvents(ctx context.Context, events []proton.AddressEvent) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type LabelEventHandler interface {
|
||||||
|
HandleLabelEvents(ctx context.Context, events []proton.LabelEvent) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageEventHandler interface {
|
||||||
|
HandleMessageEvents(ctx context.Context, events []proton.MessageEvent) error
|
||||||
|
}
|
||||||
@ -47,10 +47,7 @@ type Service struct {
|
|||||||
log *logrus.Entry
|
log *logrus.Entry
|
||||||
identity State
|
identity State
|
||||||
|
|
||||||
userSubscriber *userevents.UserChanneledSubscriber
|
subscription *userevents.EventChanneledSubscriber
|
||||||
addressSubscriber *userevents.AddressChanneledSubscriber
|
|
||||||
usedSpaceSubscriber *userevents.UserUsedSpaceChanneledSubscriber
|
|
||||||
refreshSubscriber *userevents.RefreshChanneledSubscriber
|
|
||||||
|
|
||||||
bridgePassProvider BridgePassProvider
|
bridgePassProvider BridgePassProvider
|
||||||
telemetry Telemetry
|
telemetry Telemetry
|
||||||
@ -74,12 +71,9 @@ func NewService(
|
|||||||
"service": "user-identity",
|
"service": "user-identity",
|
||||||
"user": state.User.ID,
|
"user": state.User.ID,
|
||||||
}),
|
}),
|
||||||
userSubscriber: userevents.NewUserSubscriber(subscriberName),
|
subscription: userevents.NewEventSubscriber(subscriberName),
|
||||||
refreshSubscriber: userevents.NewRefreshSubscriber(subscriberName),
|
bridgePassProvider: bridgePassProvider,
|
||||||
addressSubscriber: userevents.NewAddressSubscriber(subscriberName),
|
telemetry: telemetry,
|
||||||
usedSpaceSubscriber: userevents.NewUserUsedSpaceSubscriber(subscriberName),
|
|
||||||
bridgePassProvider: bridgePassProvider,
|
|
||||||
telemetry: telemetry,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,134 +102,30 @@ func (s *Service) CheckAuth(ctx context.Context, email string, password []byte)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) run(ctx context.Context) {
|
func (s *Service) HandleUsedSpaceEvent(ctx context.Context, newSpace int) error {
|
||||||
s.log.WithFields(logrus.Fields{
|
s.log.Info("Handling User Space Changed event")
|
||||||
"numAddr": len(s.identity.Addresses),
|
|
||||||
}).Info("Starting user identity service")
|
|
||||||
defer s.log.Info("Exiting Service")
|
|
||||||
|
|
||||||
s.registerSubscription()
|
if s.identity.OnUserSpaceChanged(newSpace) {
|
||||||
defer s.unregisterSubscription()
|
s.eventPublisher.PublishEvent(ctx, events.UsedSpaceChanged{
|
||||||
|
UserID: s.identity.User.ID,
|
||||||
defer s.cpc.Close()
|
UsedSpace: newSpace,
|
||||||
|
})
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case r, ok := <-s.cpc.ReceiveCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch req := r.Value().(type) {
|
|
||||||
case *resyncReq:
|
|
||||||
err := s.identity.OnRefreshEvent(ctx)
|
|
||||||
r.Reply(ctx, nil, err)
|
|
||||||
|
|
||||||
case *getUserReq:
|
|
||||||
r.Reply(ctx, s.identity.User, nil)
|
|
||||||
|
|
||||||
case *getAddressesReq:
|
|
||||||
r.Reply(ctx, maps.Clone(s.identity.Addresses), nil)
|
|
||||||
|
|
||||||
case *checkAuthReq:
|
|
||||||
id, err := s.identity.CheckAuth(req.email, req.password, s.bridgePassProvider, s.telemetry)
|
|
||||||
r.Reply(ctx, id, err)
|
|
||||||
|
|
||||||
default:
|
|
||||||
s.log.Error("Invalid request")
|
|
||||||
}
|
|
||||||
|
|
||||||
case evt, ok := <-s.userSubscriber.OnEventCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
evt.Consume(func(user proton.User) error {
|
|
||||||
s.onUserEvent(ctx, user)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
case evt, ok := <-s.refreshSubscriber.OnEventCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
evt.Consume(func(_ proton.RefreshFlag) error {
|
|
||||||
return s.onRefreshEvent(ctx)
|
|
||||||
})
|
|
||||||
case evt, ok := <-s.usedSpaceSubscriber.OnEventCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
evt.Consume(func(usedSpace int) error {
|
|
||||||
s.onUserSpaceChanged(ctx, usedSpace)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
case evt, ok := <-s.addressSubscriber.OnEventCh():
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
evt.Consume(func(events []proton.AddressEvent) error {
|
|
||||||
return s.onAddressEvent(ctx, events)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) registerSubscription() {
|
func (s *Service) HandleUserEvent(ctx context.Context, user *proton.User) error {
|
||||||
s.eventService.Subscribe(userevents.Subscription{
|
|
||||||
Refresh: s.refreshSubscriber,
|
|
||||||
User: s.userSubscriber,
|
|
||||||
Address: s.addressSubscriber,
|
|
||||||
UserUsedSpace: s.usedSpaceSubscriber,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) unregisterSubscription() {
|
|
||||||
s.eventService.Unsubscribe(userevents.Subscription{
|
|
||||||
Refresh: s.refreshSubscriber,
|
|
||||||
User: s.userSubscriber,
|
|
||||||
Address: s.addressSubscriber,
|
|
||||||
UserUsedSpace: s.usedSpaceSubscriber,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) onUserEvent(ctx context.Context, user proton.User) {
|
|
||||||
s.log.WithField("username", logging.Sensitive(user.Name)).Info("Handling user event")
|
s.log.WithField("username", logging.Sensitive(user.Name)).Info("Handling user event")
|
||||||
s.identity.OnUserEvent(user)
|
s.identity.OnUserEvent(*user)
|
||||||
s.eventPublisher.PublishEvent(ctx, events.UserChanged{
|
s.eventPublisher.PublishEvent(ctx, events.UserChanged{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) onRefreshEvent(ctx context.Context) error {
|
|
||||||
s.log.Info("Handling refresh event")
|
|
||||||
|
|
||||||
if err := s.identity.OnRefreshEvent(ctx); err != nil {
|
|
||||||
s.log.WithError(err).Error("Failed to handle refresh event")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.eventPublisher.PublishEvent(ctx, events.UserRefreshed{
|
|
||||||
UserID: s.identity.User.ID,
|
|
||||||
CancelEventPool: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) onUserSpaceChanged(ctx context.Context, value int) {
|
func (s *Service) HandleAddressEvents(ctx context.Context, addressEvents []proton.AddressEvent) error {
|
||||||
s.log.Info("Handling User Space Changed event")
|
|
||||||
if !s.identity.OnUserSpaceChanged(value) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.eventPublisher.PublishEvent(ctx, events.UsedSpaceChanged{
|
|
||||||
UserID: s.identity.User.ID,
|
|
||||||
UsedSpace: value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Service) onAddressEvent(ctx context.Context, addressEvents []proton.AddressEvent) error {
|
|
||||||
s.log.Infof("Handling Address Events (%v)", len(addressEvents))
|
s.log.Infof("Handling Address Events (%v)", len(addressEvents))
|
||||||
|
|
||||||
for idx, event := range addressEvents {
|
for idx, event := range addressEvents {
|
||||||
@ -305,6 +195,86 @@ func (s *Service) onAddressEvent(ctx context.Context, addressEvents []proton.Add
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) HandleRefreshEvent(ctx context.Context, _ proton.RefreshFlag) error {
|
||||||
|
s.log.Info("Handling refresh event")
|
||||||
|
|
||||||
|
if err := s.identity.OnRefreshEvent(ctx); err != nil {
|
||||||
|
s.log.WithError(err).Error("Failed to handle refresh event")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.eventPublisher.PublishEvent(ctx, events.UserRefreshed{
|
||||||
|
UserID: s.identity.User.ID,
|
||||||
|
CancelEventPool: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) run(ctx context.Context) {
|
||||||
|
s.log.WithFields(logrus.Fields{
|
||||||
|
"numAddr": len(s.identity.Addresses),
|
||||||
|
}).Info("Starting user identity service")
|
||||||
|
defer s.log.Info("Exiting Service")
|
||||||
|
|
||||||
|
eventHandler := userevents.EventHandler{
|
||||||
|
UserHandler: s,
|
||||||
|
AddressHandler: s,
|
||||||
|
UsedSpaceHandler: s,
|
||||||
|
RefreshHandler: s,
|
||||||
|
}
|
||||||
|
|
||||||
|
s.registerSubscription()
|
||||||
|
defer s.unregisterSubscription()
|
||||||
|
|
||||||
|
defer s.cpc.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case r, ok := <-s.cpc.ReceiveCh():
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch req := r.Value().(type) {
|
||||||
|
case *resyncReq:
|
||||||
|
err := s.identity.OnRefreshEvent(ctx)
|
||||||
|
r.Reply(ctx, nil, err)
|
||||||
|
|
||||||
|
case *getUserReq:
|
||||||
|
r.Reply(ctx, s.identity.User, nil)
|
||||||
|
|
||||||
|
case *getAddressesReq:
|
||||||
|
r.Reply(ctx, maps.Clone(s.identity.Addresses), nil)
|
||||||
|
|
||||||
|
case *checkAuthReq:
|
||||||
|
id, err := s.identity.CheckAuth(req.email, req.password, s.bridgePassProvider, s.telemetry)
|
||||||
|
r.Reply(ctx, id, err)
|
||||||
|
|
||||||
|
default:
|
||||||
|
s.log.Error("Invalid request")
|
||||||
|
}
|
||||||
|
|
||||||
|
case evt, ok := <-s.subscription.OnEventCh():
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
evt.Consume(func(event proton.Event) error {
|
||||||
|
return eventHandler.OnEvent(ctx, event)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) registerSubscription() {
|
||||||
|
s.eventService.Subscribe(s.subscription)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) unregisterSubscription() {
|
||||||
|
s.eventService.Unsubscribe(s.subscription)
|
||||||
|
}
|
||||||
|
|
||||||
func sortAddresses(addr []proton.Address) []proton.Address {
|
func sortAddresses(addr []proton.Address) []proton.Address {
|
||||||
slices.SortFunc(addr, func(a, b proton.Address) bool {
|
slices.SortFunc(addr, func(a, b proton.Address) bool {
|
||||||
return a.Order < b.Order
|
return a.Order < b.Order
|
||||||
|
|||||||
@ -39,7 +39,7 @@ func TestService_OnUserEvent(t *testing.T) {
|
|||||||
|
|
||||||
eventPublisher.EXPECT().PublishEvent(gomock.Any(), gomock.Eq(events.UserChanged{UserID: TestUserID})).Times(1)
|
eventPublisher.EXPECT().PublishEvent(gomock.Any(), gomock.Eq(events.UserChanged{UserID: TestUserID})).Times(1)
|
||||||
|
|
||||||
service.onUserEvent(context.Background(), newTestUser())
|
require.NoError(t, service.HandleUserEvent(context.Background(), newTestUser()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestService_OnUserSpaceChanged(t *testing.T) {
|
func TestService_OnUserSpaceChanged(t *testing.T) {
|
||||||
@ -50,10 +50,10 @@ func TestService_OnUserSpaceChanged(t *testing.T) {
|
|||||||
eventPublisher.EXPECT().PublishEvent(gomock.Any(), gomock.Eq(events.UsedSpaceChanged{UserID: TestUserID, UsedSpace: 1024})).Times(1)
|
eventPublisher.EXPECT().PublishEvent(gomock.Any(), gomock.Eq(events.UsedSpaceChanged{UserID: TestUserID, UsedSpace: 1024})).Times(1)
|
||||||
|
|
||||||
// Original value, no changes.
|
// Original value, no changes.
|
||||||
service.onUserSpaceChanged(context.Background(), 0)
|
require.NoError(t, service.HandleUsedSpaceEvent(context.Background(), 0))
|
||||||
|
|
||||||
// New value, event should be published.
|
// New value, event should be published.
|
||||||
service.onUserSpaceChanged(context.Background(), 1024)
|
require.NoError(t, service.HandleUsedSpaceEvent(context.Background(), 1024))
|
||||||
require.Equal(t, 1024, service.identity.User.UsedSpace)
|
require.Equal(t, 1024, service.identity.User.UsedSpace)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,14 +68,14 @@ func TestService_OnRefreshEvent(t *testing.T) {
|
|||||||
newAddresses := newTestAddressesRefreshed()
|
newAddresses := newTestAddressesRefreshed()
|
||||||
|
|
||||||
{
|
{
|
||||||
getUserCall := provider.EXPECT().GetUser(gomock.Any()).Times(1).Return(newUser, nil)
|
getUserCall := provider.EXPECT().GetUser(gomock.Any()).Times(1).Return(*newUser, nil)
|
||||||
provider.EXPECT().GetAddresses(gomock.Any()).After(getUserCall).Times(1).Return(newAddresses, nil)
|
provider.EXPECT().GetAddresses(gomock.Any()).After(getUserCall).Times(1).Return(newAddresses, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Original value, no changes.
|
// Original value, no changes.
|
||||||
require.NoError(t, service.onRefreshEvent(context.Background()))
|
require.NoError(t, service.HandleRefreshEvent(context.Background(), 0))
|
||||||
|
|
||||||
require.Equal(t, newUser, service.identity.User)
|
require.Equal(t, *newUser, service.identity.User)
|
||||||
require.Equal(t, newAddresses, service.identity.AddressesSorted)
|
require.Equal(t, newAddresses, service.identity.AddressesSorted)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ func TestService_OnAddressCreated(t *testing.T) {
|
|||||||
Email: newAddress.Email,
|
Email: newAddress.Email,
|
||||||
})).Times(1)
|
})).Times(1)
|
||||||
|
|
||||||
err := service.onAddressEvent(context.Background(), []proton.AddressEvent{
|
err := service.HandleAddressEvents(context.Background(), []proton.AddressEvent{
|
||||||
{
|
{
|
||||||
EventItem: proton.EventItem{
|
EventItem: proton.EventItem{
|
||||||
ID: "",
|
ID: "",
|
||||||
@ -121,7 +121,7 @@ func TestService_OnAddressCreatedDisabledDoesNotProduceEvent(t *testing.T) {
|
|||||||
Status: proton.AddressStatusEnabled,
|
Status: proton.AddressStatusEnabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := service.onAddressEvent(context.Background(), []proton.AddressEvent{
|
err := service.HandleAddressEvents(context.Background(), []proton.AddressEvent{
|
||||||
{
|
{
|
||||||
EventItem: proton.EventItem{
|
EventItem: proton.EventItem{
|
||||||
ID: "",
|
ID: "",
|
||||||
@ -146,7 +146,7 @@ func TestService_OnAddressCreatedDuplicateDoesNotProduceEvent(t *testing.T) {
|
|||||||
Status: proton.AddressStatusDisabled,
|
Status: proton.AddressStatusDisabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := service.onAddressEvent(context.Background(), []proton.AddressEvent{
|
err := service.HandleAddressEvents(context.Background(), []proton.AddressEvent{
|
||||||
{
|
{
|
||||||
EventItem: proton.EventItem{
|
EventItem: proton.EventItem{
|
||||||
ID: "",
|
ID: "",
|
||||||
@ -177,7 +177,7 @@ func TestService_OnAddressUpdated(t *testing.T) {
|
|||||||
Email: newAddress.Email,
|
Email: newAddress.Email,
|
||||||
})).Times(1)
|
})).Times(1)
|
||||||
|
|
||||||
err := service.onAddressEvent(context.Background(), []proton.AddressEvent{
|
err := service.HandleAddressEvents(context.Background(), []proton.AddressEvent{
|
||||||
{
|
{
|
||||||
EventItem: proton.EventItem{
|
EventItem: proton.EventItem{
|
||||||
ID: "",
|
ID: "",
|
||||||
@ -221,7 +221,7 @@ func TestService_OnAddressUpdatedDisableFollowedByEnable(t *testing.T) {
|
|||||||
})).Times(1).After(disabledCall)
|
})).Times(1).After(disabledCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := service.onAddressEvent(context.Background(), []proton.AddressEvent{
|
err := service.HandleAddressEvents(context.Background(), []proton.AddressEvent{
|
||||||
{
|
{
|
||||||
EventItem: proton.EventItem{
|
EventItem: proton.EventItem{
|
||||||
ID: "",
|
ID: "",
|
||||||
@ -234,7 +234,7 @@ func TestService_OnAddressUpdatedDisableFollowedByEnable(t *testing.T) {
|
|||||||
|
|
||||||
require.Equal(t, newAddressDisabled, service.identity.Addresses[newAddressEnabled.ID])
|
require.Equal(t, newAddressDisabled, service.identity.Addresses[newAddressEnabled.ID])
|
||||||
|
|
||||||
err = service.onAddressEvent(context.Background(), []proton.AddressEvent{
|
err = service.HandleAddressEvents(context.Background(), []proton.AddressEvent{
|
||||||
{
|
{
|
||||||
EventItem: proton.EventItem{
|
EventItem: proton.EventItem{
|
||||||
ID: "",
|
ID: "",
|
||||||
@ -265,7 +265,7 @@ func TestService_OnAddressUpdateCreatedIfNotExists(t *testing.T) {
|
|||||||
Email: newAddress.Email,
|
Email: newAddress.Email,
|
||||||
})).Times(1)
|
})).Times(1)
|
||||||
|
|
||||||
err := service.onAddressEvent(context.Background(), []proton.AddressEvent{
|
err := service.HandleAddressEvents(context.Background(), []proton.AddressEvent{
|
||||||
{
|
{
|
||||||
EventItem: proton.EventItem{
|
EventItem: proton.EventItem{
|
||||||
ID: "",
|
ID: "",
|
||||||
@ -296,7 +296,7 @@ func TestService_OnAddressDeleted(t *testing.T) {
|
|||||||
Email: address.Email,
|
Email: address.Email,
|
||||||
})).Times(1)
|
})).Times(1)
|
||||||
|
|
||||||
err := service.onAddressEvent(context.Background(), []proton.AddressEvent{
|
err := service.HandleAddressEvents(context.Background(), []proton.AddressEvent{
|
||||||
{
|
{
|
||||||
EventItem: proton.EventItem{
|
EventItem: proton.EventItem{
|
||||||
ID: address.ID,
|
ID: address.ID,
|
||||||
@ -320,7 +320,7 @@ func TestService_OnAddressDeleteDisabledDoesNotProduceEvent(t *testing.T) {
|
|||||||
Status: proton.AddressStatusDisabled,
|
Status: proton.AddressStatusDisabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := service.onAddressEvent(context.Background(), []proton.AddressEvent{
|
err := service.HandleAddressEvents(context.Background(), []proton.AddressEvent{
|
||||||
{
|
{
|
||||||
EventItem: proton.EventItem{
|
EventItem: proton.EventItem{
|
||||||
ID: address.ID,
|
ID: address.ID,
|
||||||
@ -344,7 +344,7 @@ func TestService_OnAddressDeletedUnknownDoesNotProduceEvent(t *testing.T) {
|
|||||||
Status: proton.AddressStatusEnabled,
|
Status: proton.AddressStatusEnabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := service.onAddressEvent(context.Background(), []proton.AddressEvent{
|
err := service.HandleAddressEvents(context.Background(), []proton.AddressEvent{
|
||||||
{
|
{
|
||||||
EventItem: proton.EventItem{
|
EventItem: proton.EventItem{
|
||||||
ID: address.ID,
|
ID: address.ID,
|
||||||
@ -364,12 +364,12 @@ func newTestService(_ *testing.T, mockCtrl *gomock.Controller) (*Service, *mocks
|
|||||||
telemetry := mocks.NewMockTelemetry(mockCtrl)
|
telemetry := mocks.NewMockTelemetry(mockCtrl)
|
||||||
bridgePassProvider := NewFixedBridgePassProvider([]byte("hello"))
|
bridgePassProvider := NewFixedBridgePassProvider([]byte("hello"))
|
||||||
|
|
||||||
service := NewService(subscribable, eventPublisher, NewState(user, newTestAddresses(), provider), bridgePassProvider, telemetry)
|
service := NewService(subscribable, eventPublisher, NewState(*user, newTestAddresses(), provider), bridgePassProvider, telemetry)
|
||||||
return service, eventPublisher, provider
|
return service, eventPublisher, provider
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestUser() proton.User {
|
func newTestUser() *proton.User {
|
||||||
return proton.User{
|
return &proton.User{
|
||||||
ID: TestUserID,
|
ID: TestUserID,
|
||||||
Name: "Foo",
|
Name: "Foo",
|
||||||
DisplayName: "Foo",
|
DisplayName: "Foo",
|
||||||
@ -383,8 +383,8 @@ func newTestUser() proton.User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestUserRefreshed() proton.User {
|
func newTestUserRefreshed() *proton.User {
|
||||||
return proton.User{
|
return &proton.User{
|
||||||
ID: TestUserID,
|
ID: TestUserID,
|
||||||
Name: "Alternate",
|
Name: "Alternate",
|
||||||
DisplayName: "Universe",
|
DisplayName: "Universe",
|
||||||
|
|||||||
Reference in New Issue
Block a user