@@ -517,6 +517,109 @@ func TestInvalidConfig(t *testing.T) {
517
517
require .ErrorIs (t ,err ,notifications .ErrInvalidDispatchTimeout )
518
518
}
519
519
520
+ func TestNotifierPaused (t * testing.T ) {
521
+ t .Parallel ()
522
+
523
+ ctx ,logger ,db := setup (t )
524
+
525
+ // Mock server to simulate webhook endpoint.
526
+ server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter ,_ * http.Request ) {
527
+ w .WriteHeader (http .StatusNoContent )
528
+ }))
529
+ defer server .Close ()
530
+
531
+ endpoint ,err := url .Parse (server .URL )
532
+ require .NoError (t ,err )
533
+
534
+ // given
535
+ fetchInterval := time .Nanosecond // manager should process messages immediately
536
+
537
+ cfg := defaultNotificationsConfig (database .NotificationMethodWebhook )
538
+ cfg .Webhook = codersdk.NotificationsWebhookConfig {
539
+ Endpoint :* serpent .URLOf (endpoint ),
540
+ }
541
+ cfg .FetchInterval = * serpent .DurationOf (& fetchInterval )
542
+ mgr ,err := notifications .NewManager (cfg ,db ,logger .Named ("manager" ))
543
+ require .NoError (t ,err )
544
+ t .Cleanup (func () {
545
+ assert .NoError (t ,mgr .Stop (ctx ))
546
+ })
547
+ enq ,err := notifications .NewStoreEnqueuer (cfg ,db ,defaultHelpers (),logger .Named ("enqueuer" ))
548
+ require .NoError (t ,err )
549
+
550
+ user := dbgen .User (t ,db , database.User {
551
+ Email :"bob@coder.com" ,
552
+ Username :"bob" ,
553
+ Name :"Robert McBobbington" ,
554
+ })
555
+
556
+ input := map [string ]string {"a" :"b" }
557
+
558
+ // Pause notifier
559
+ settingsJSON ,err := json .Marshal (& codersdk.NotificationsSettings {
560
+ NotifierPaused :true ,
561
+ })
562
+ require .NoError (t ,err )
563
+ err = db .UpsertNotificationsSettings (ctx ,string (settingsJSON ))
564
+ require .NoError (t ,err )
565
+
566
+ // Start notification manager
567
+ mgr .Run (ctx )
568
+
569
+ // when
570
+ // Enqueue a bunch of messages
571
+ messagesCount := 50
572
+ var wg sync.WaitGroup
573
+ wg .Add (1 )
574
+ go func () {
575
+ for i := 0 ;i < messagesCount ;i ++ {
576
+ _ ,err := enq .Enqueue (ctx ,user .ID ,notifications .TemplateWorkspaceDeleted ,input ,"test" )
577
+ if err != nil {
578
+ logger .Named ("enqueuer-test" ).Error (ctx ,"unable to enqueue message" ,slog .Error (err ))
579
+ return
580
+ }
581
+ }
582
+ wg .Done ()
583
+ }()
584
+
585
+ // then
586
+ // Wait until they are all stored in the database
587
+ require .Eventually (t ,func ()bool {
588
+ pendingMessages ,err := db .GetNotificationMessagesByStatus (ctx , database.GetNotificationMessagesByStatusParams {
589
+ Status :database .NotificationMessageStatusPending ,
590
+ Limit :int32 (messagesCount ),
591
+ })
592
+ if err != nil {
593
+ return false
594
+ }
595
+ return len (pendingMessages )== messagesCount
596
+ },testutil .WaitShort ,testutil .IntervalFast )
597
+
598
+ wg .Wait ()
599
+
600
+ // when
601
+ // Unpause notifier
602
+ settingsJSON ,err = json .Marshal (& codersdk.NotificationsSettings {
603
+ NotifierPaused :false ,
604
+ })
605
+ require .NoError (t ,err )
606
+ err = db .UpsertNotificationsSettings (ctx ,string (settingsJSON ))
607
+ require .NoError (t ,err )
608
+
609
+ // test
610
+ // Check if messages have been dispatched
611
+ require .Eventually (t ,func ()bool {
612
+ pendingMessages ,err := db .GetNotificationMessagesByStatus (ctx , database.GetNotificationMessagesByStatusParams {
613
+ Status :database .NotificationMessageStatusPending ,
614
+ Limit :int32 (messagesCount ),
615
+ })
616
+ if err != nil {
617
+ return false
618
+ }
619
+ return len (pendingMessages )== 0
620
+ },testutil .WaitShort ,testutil .IntervalFast )
621
+ }
622
+
520
623
type fakeHandler struct {
521
624
mu sync.RWMutex
522
625