(t *testing.T)
| 611 | } |
| 612 | |
| 613 | func TestNotifierPaused(t *testing.T) { |
| 614 | t.Parallel() |
| 615 | |
| 616 | // Setup. |
| 617 | |
| 618 | ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong)) |
| 619 | store, pubsub := dbtestutil.NewDB(t) |
| 620 | logger := testutil.Logger(t) |
| 621 | |
| 622 | // Prepare the test. |
| 623 | handler := &fakeHandler{} |
| 624 | method := database.NotificationMethodSmtp |
| 625 | user := createSampleUser(t, store) |
| 626 | |
| 627 | const fetchInterval = time.Millisecond * 100 |
| 628 | cfg := defaultNotificationsConfig(method) |
| 629 | cfg.FetchInterval = serpent.Duration(fetchInterval) |
| 630 | mgr, err := notifications.NewManager(cfg, store, pubsub, defaultHelpers(), createMetrics(), logger.Named("manager")) |
| 631 | require.NoError(t, err) |
| 632 | mgr.WithHandlers(map[database.NotificationMethod]notifications.Handler{ |
| 633 | method: handler, |
| 634 | database.NotificationMethodInbox: &fakeHandler{}, |
| 635 | }) |
| 636 | t.Cleanup(func() { |
| 637 | assert.NoError(t, mgr.Stop(ctx)) |
| 638 | }) |
| 639 | enq, err := notifications.NewStoreEnqueuer(cfg, store, defaultHelpers(), logger.Named("enqueuer"), quartz.NewReal()) |
| 640 | require.NoError(t, err) |
| 641 | |
| 642 | // Pause the notifier. |
| 643 | settingsJSON, err := json.Marshal(&codersdk.NotificationsSettings{NotifierPaused: true}) |
| 644 | require.NoError(t, err) |
| 645 | err = store.UpsertNotificationsSettings(ctx, string(settingsJSON)) |
| 646 | require.NoError(t, err) |
| 647 | |
| 648 | // Start the manager so that notifications are processed, except it will be paused at this point. |
| 649 | // If it is started before pausing, there's a TOCTOU possibility between checking whether the notifier is paused or |
| 650 | // not, and processing the messages (see notifier.run). |
| 651 | mgr.Run(ctx) |
| 652 | |
| 653 | // Notifier is paused, enqueue the next message. |
| 654 | sid, err := enq.Enqueue(ctx, user.ID, notifications.TemplateWorkspaceDeleted, map[string]string{"type": "success", "i": "1"}, "test") |
| 655 | require.NoError(t, err) |
| 656 | |
| 657 | // Ensure we have a pending message and it's the expected one. |
| 658 | pendingMessages, err := store.GetNotificationMessagesByStatus(ctx, database.GetNotificationMessagesByStatusParams{ |
| 659 | Status: database.NotificationMessageStatusPending, |
| 660 | Limit: 10, |
| 661 | }) |
| 662 | require.NoError(t, err) |
| 663 | require.Len(t, pendingMessages, 2) |
| 664 | require.Equal(t, pendingMessages[0].ID.String(), sid[0].String()) |
| 665 | require.Equal(t, pendingMessages[1].ID.String(), sid[1].String()) |
| 666 | |
| 667 | // Wait a few fetch intervals to be sure that no new notifications are being sent. |
| 668 | // TODO: use quartz instead. |
| 669 | // nolint:gocritic // These magic numbers are fine. |
| 670 | require.Eventually(t, func() bool { |
nothing calls this directly
no test coverage detected