Skip to content

Commit

Permalink
refactor notifier test and add register tests
Browse files Browse the repository at this point in the history
  • Loading branch information
almostinf committed Nov 10, 2023
1 parent 0e3d388 commit e0d82a4
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 49 deletions.
2 changes: 2 additions & 0 deletions cmd/notifier/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,15 @@ func main() {
notifierConfig := config.Notifier.getSettings(logger)

notifierMetrics := metrics.ConfigureNotifierMetrics(telemetry.Metrics, serviceName)
scheduler := notifier.NewScheduler(database, logger, notifierMetrics)
sender := notifier.NewNotifier(
database,
logger,
notifierConfig,
notifierMetrics,
metricSourceProvider,
imageStoreMap,
scheduler,
)

// Register moira senders
Expand Down
4 changes: 3 additions & 1 deletion integration_tests/notifier/notifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ func TestNotifier(t *testing.T) {
database.PushNotificationEvent(&event, true) //nolint

metricsSourceProvider := metricSource.CreateMetricSourceProvider(local.Create(database), nil, nil)
scheduler := notifier.NewScheduler(database, logger, notifierMetrics)

notifierInstance := notifier.NewNotifier(
database,
Expand All @@ -95,6 +96,7 @@ func TestNotifier(t *testing.T) {
notifierMetrics,
metricsSourceProvider,
map[string]moira.ImageStore{},
scheduler,
)

sender := mock_moira_alert.NewMockSender(mockCtrl)
Expand All @@ -113,7 +115,7 @@ func TestNotifier(t *testing.T) {
Database: database,
Logger: logger,
Metrics: notifierMetrics,
Scheduler: notifier.NewScheduler(database, logger, notifierMetrics),
Scheduler: scheduler,
}

fetchNotificationsWorker := notifications.FetchNotificationsWorker{
Expand Down
17 changes: 15 additions & 2 deletions notifier/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,21 @@ type StandardNotifier struct {
}

// NewNotifier is initializer for StandardNotifier
func NewNotifier(database moira.Database, logger moira.Logger, config Config, metrics *metrics.NotifierMetrics, metricSourceProvider *metricSource.SourceProvider, imageStoreMap map[string]moira.ImageStore) *StandardNotifier {
func NewNotifier(
database moira.Database,
logger moira.Logger,
config Config,
metrics *metrics.NotifierMetrics,
metricSourceProvider *metricSource.SourceProvider,
imageStoreMap map[string]moira.ImageStore,
scheduler Scheduler,
) *StandardNotifier {
return &StandardNotifier{
senders: make(map[string]moira.Sender),
sendersNotificationsCh: make(map[string]chan NotificationPackage),
logger: logger,
database: database,
scheduler: NewScheduler(database, logger, metrics),
scheduler: scheduler,
config: config,
metrics: metrics,
metricSourceProvider: metricSourceProvider,
Expand Down Expand Up @@ -150,6 +158,11 @@ func (notifier *StandardNotifier) GetReadBatchSize() int64 {
return notifier.config.ReadBatchSize
}

// GetSendersTypeByName returns the type of the sender by its name
func (notifier *StandardNotifier) GetSendersTypeByName(name string) string {
return notifier.sendersNameToType[name]
}

func (notifier *StandardNotifier) resend(pkg *NotificationPackage, reason string) {
if pkg.DontResend {
return
Expand Down
90 changes: 46 additions & 44 deletions notifier/notifier_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package notifier
package notifier_test

import (
"fmt"
Expand All @@ -16,20 +16,29 @@ import (
"github.com/moira-alert/moira/metrics"
mock_moira_alert "github.com/moira-alert/moira/mock/moira-alert"
mock_scheduler "github.com/moira-alert/moira/mock/scheduler"
"github.com/moira-alert/moira/notifier"
)

var (
plots [][]byte
shutdown = make(chan struct{})
plots [][]byte
shutdown = make(chan struct{})
location = &time.Location{}
dateTimeFormat = "15:04 02.01.2006"
defaultConfig = notifier.Config{
SendingTimeout: time.Millisecond * 10,
ResendingTimeout: time.Hour * 24,
Location: location,
DateTimeFormat: dateTimeFormat,
}
)

var (
mockCtrl *gomock.Controller
sender *mock_moira_alert.MockSender
notifier *StandardNotifier
scheduler *mock_scheduler.MockScheduler
dataBase *mock_moira_alert.MockDatabase
logger moira.Logger
mockCtrl *gomock.Controller
sender *mock_moira_alert.MockSender
standardNotifier *notifier.StandardNotifier
scheduler *mock_scheduler.MockScheduler
dataBase *mock_moira_alert.MockDatabase
logger moira.Logger
)

func TestGetMetricNames(t *testing.T) {
Expand All @@ -41,7 +50,7 @@ func TestGetMetricNames(t *testing.T) {
})

Convey("Test package with no trigger events", func() {
pkg := NotificationPackage{}
pkg := notifier.NotificationPackage{}
for _, event := range notificationsPackage.Events {
if event.IsTriggerEvent {
event.IsTriggerEvent = false
Expand All @@ -55,7 +64,7 @@ func TestGetMetricNames(t *testing.T) {
})

Convey("Test empty notification package", t, func() {
emptyNotificationPackage := NotificationPackage{}
emptyNotificationPackage := notifier.NotificationPackage{}
actual := emptyNotificationPackage.GetMetricNames()
So(actual, ShouldHaveLength, 0)
})
Expand All @@ -70,19 +79,19 @@ func TestGetWindow(t *testing.T) {
})

Convey("Test empty notification package", t, func() {
emptyNotificationPackage := NotificationPackage{}
emptyNotificationPackage := notifier.NotificationPackage{}
_, _, err := emptyNotificationPackage.GetWindow()
So(err, ShouldResemble, fmt.Errorf("not enough data to resolve package window"))
})
}

func TestUnknownContactType(t *testing.T) {
configureNotifier(t)
configureNotifier(t, defaultConfig)
defer afterTest()

var eventsData moira.NotificationEvents = []moira.NotificationEvent{event}

pkg := NotificationPackage{
pkg := notifier.NotificationPackage{
Events: eventsData,
Contact: moira.ContactData{
Type: "unknown contact",
Expand All @@ -93,29 +102,30 @@ func TestUnknownContactType(t *testing.T) {
dataBase.EXPECT().AddNotification(&notification).Return(nil)

var wg sync.WaitGroup
notifier.Send(&pkg, &wg)
standardNotifier.Send(&pkg, &wg)
wg.Wait()
}

func TestFailSendEvent(t *testing.T) {
configureNotifier(t)
configureNotifier(t, defaultConfig)
defer afterTest()

var eventsData moira.NotificationEvents = []moira.NotificationEvent{event}

pkg := NotificationPackage{
pkg := notifier.NotificationPackage{
Events: eventsData,
Contact: moira.ContactData{
Type: "test",
},
}

notification := moira.ScheduledNotification{}
sender.EXPECT().SendEvents(eventsData, pkg.Contact, pkg.Trigger, plots, pkg.Throttled).Return(fmt.Errorf("Cant't send"))
scheduler.EXPECT().ScheduleNotification(gomock.Any(), event, pkg.Trigger, pkg.Contact, pkg.Plotting, pkg.Throttled, pkg.FailCount+1, gomock.Any()).Return(&notification)
dataBase.EXPECT().AddNotification(&notification).Return(nil)

var wg sync.WaitGroup
notifier.Send(&pkg, &wg)
standardNotifier.Send(&pkg, &wg)
wg.Wait()
time.Sleep(time.Second * 2)
}
Expand All @@ -125,12 +135,12 @@ func TestNoResendForSendToBrokenContact(t *testing.T) {
t.Skip("skipping test in short mode.")
}

configureNotifier(t)
configureNotifier(t, defaultConfig)
defer afterTest()

var eventsData moira.NotificationEvents = []moira.NotificationEvent{event}

pkg := NotificationPackage{
pkg := notifier.NotificationPackage{
Events: eventsData,
Contact: moira.ContactData{
Type: "test",
Expand All @@ -140,20 +150,20 @@ func TestNoResendForSendToBrokenContact(t *testing.T) {
Return(moira.NewSenderBrokenContactError(fmt.Errorf("some sender reason")))

var wg sync.WaitGroup
notifier.Send(&pkg, &wg)
standardNotifier.Send(&pkg, &wg)
wg.Wait()
time.Sleep(time.Second * 2)
}

func TestTimeout(t *testing.T) {
configureNotifier(t)
configureNotifier(t, defaultConfig)
var wg sync.WaitGroup
defer afterTest()

var eventsData moira.NotificationEvents = []moira.NotificationEvent{event}

// Configure events with long sending time
pkg := NotificationPackage{
pkg := notifier.NotificationPackage{
Events: eventsData,
Contact: moira.ContactData{
Type: "test",
Expand All @@ -163,16 +173,16 @@ func TestTimeout(t *testing.T) {
sender.EXPECT().SendEvents(eventsData, pkg.Contact, pkg.Trigger, plots, pkg.Throttled).Return(nil).Do(func(arg0, arg1, arg2, arg3, arg4 interface{}) {
fmt.Print("Trying to send for 10 second")
time.Sleep(time.Second * 10)
}).Times(maxParallelSendsPerSender)
}).Times(standardNotifier.GetParallelSendsPerSender())

for i := 0; i < maxParallelSendsPerSender; i++ {
notifier.Send(&pkg, &wg)
for i := 0; i < standardNotifier.GetParallelSendsPerSender(); i++ {
standardNotifier.Send(&pkg, &wg)
wg.Wait()
}

// Configure timeouted event
notification := moira.ScheduledNotification{}
pkg2 := NotificationPackage{
pkg2 := notifier.NotificationPackage{
Events: eventsData,
Contact: moira.ContactData{
Type: "test",
Expand All @@ -183,7 +193,7 @@ func TestTimeout(t *testing.T) {
scheduler.EXPECT().ScheduleNotification(gomock.Any(), event, pkg2.Trigger, pkg2.Contact, pkg.Plotting, pkg2.Throttled, pkg2.FailCount+1, gomock.Any()).Return(&notification)
dataBase.EXPECT().AddNotification(&notification).Return(nil).Do(func(f ...interface{}) { close(shutdown) })

notifier.Send(&pkg2, &wg)
standardNotifier.Send(&pkg2, &wg)
wg.Wait()
waitTestEnd()
}
Expand All @@ -198,16 +208,8 @@ func waitTestEnd() {
}
}

func configureNotifier(t *testing.T) {
func configureNotifier(t *testing.T, config notifier.Config) {
notifierMetrics := metrics.ConfigureNotifierMetrics(metrics.NewDummyRegistry(), "notifier")
var location, _ = time.LoadLocation("UTC")
dateTimeFormat := "15:04 02.01.2006"
config := Config{
SendingTimeout: time.Millisecond * 10,
ResendingTimeout: time.Hour * 24,
Location: location,
DateTimeFormat: dateTimeFormat,
}

mockCtrl = gomock.NewController(t)
dataBase = mock_moira_alert.NewMockDatabase(mockCtrl)
Expand All @@ -216,25 +218,25 @@ func configureNotifier(t *testing.T) {
sender = mock_moira_alert.NewMockSender(mockCtrl)
metricsSourceProvider := metricSource.CreateMetricSourceProvider(local.Create(dataBase), nil, nil)

notifier = NewNotifier(dataBase, logger, config, notifierMetrics, metricsSourceProvider, map[string]moira.ImageStore{})
notifier.scheduler = scheduler
standardNotifier = notifier.NewNotifier(dataBase, logger, config, notifierMetrics, metricsSourceProvider, map[string]moira.ImageStore{}, scheduler)
senderSettings := map[string]interface{}{
"type": "test",
}

sender.EXPECT().Init(senderSettings, logger, location, "15:04 02.01.2006").Return(nil)

notifier.RegisterSender(senderSettings, sender) //nolint
err := standardNotifier.RegisterSender(senderSettings, sender)

Convey("Should return one sender", t, func() {
So(notifier.GetSenders(), ShouldResemble, map[string]bool{"test": true})
So(notifier.sendersNameToType["test"], ShouldEqual, senderSettings["type"])
So(err, ShouldBeNil)
So(standardNotifier.GetSenders(), ShouldResemble, map[string]bool{"test": true})
So(standardNotifier.GetSendersTypeByName("test"), ShouldEqual, senderSettings["type"])
})
}

func afterTest() {
mockCtrl.Finish()
notifier.StopSenders()
standardNotifier.StopSenders()
}

var subID = "SubscriptionID-000000000000001"
Expand All @@ -247,7 +249,7 @@ var event = moira.NotificationEvent{
SubscriptionID: &subID,
}

var notificationsPackage = NotificationPackage{
var notificationsPackage = notifier.NotificationPackage{
Events: []moira.NotificationEvent{
{Metric: "metricName1", Timestamp: 15, IsTriggerEvent: false},
{Metric: "metricName2", Timestamp: 11, IsTriggerEvent: false},
Expand Down
10 changes: 8 additions & 2 deletions notifier/registrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ const (
func (notifier *StandardNotifier) RegisterSenders(connector moira.Database) error { //nolint
var err error
for _, senderSettings := range notifier.config.Senders {
senderSettings["front_uri"] = notifier.config.FrontURL

senderType, ok := senderSettings["type"].(string)
if !ok {
return fmt.Errorf("failed to get sender type from settings: %w", err)
return fmt.Errorf("failed to get sender type from settings")
}

if sender, ok := notifier.senders[senderType]; ok {
Expand All @@ -56,7 +58,6 @@ func (notifier *StandardNotifier) RegisterSenders(connector moira.Database) erro
}
}

senderSettings["front_uri"] = notifier.config.FrontURL
switch senderType {
case mailSender:
err = notifier.RegisterSender(senderSettings, &mail.Sender{})
Expand Down Expand Up @@ -158,6 +159,11 @@ func (notifier *StandardNotifier) RegisterSender(senderSettings map[string]inter

const maxParallelSendsPerSender = 16

// GetParallelSendsPerSender returns the maximum number of running goroutines for each sentinel
func (notifier *StandardNotifier) GetParallelSendsPerSender() int {
return maxParallelSendsPerSender
}

func (notifier *StandardNotifier) runSenders(sender moira.Sender, eventsChannel chan NotificationPackage) {
for i := 0; i < maxParallelSendsPerSender; i++ {
notifier.waitGroup.Add(1)
Expand Down
Loading

0 comments on commit e0d82a4

Please sign in to comment.