TestExpiredLeaseIsRequeued validates that notification messages which are left in "leased" status will be requeued once their lease expires. "leased" is the status which messages are set to when they are acquired for processing, and this should not be a terminal state unless the Manager shuts down u
(t *testing.T)
| 486 | // state unless the Manager shuts down ungracefully; the Manager is responsible for updating these messages' statuses once |
| 487 | // they have been processed. |
| 488 | func TestExpiredLeaseIsRequeued(t *testing.T) { |
| 489 | t.Parallel() |
| 490 | |
| 491 | ctx := dbauthz.AsNotifier(testutil.Context(t, testutil.WaitSuperLong)) |
| 492 | store, pubsub := dbtestutil.NewDB(t) |
| 493 | logger := testutil.Logger(t) |
| 494 | |
| 495 | // GIVEN: a manager which has its updates intercepted and paused until measurements can be taken |
| 496 | |
| 497 | const ( |
| 498 | leasePeriod = time.Second |
| 499 | msgCount = 5 |
| 500 | method = database.NotificationMethodSmtp |
| 501 | ) |
| 502 | |
| 503 | cfg := defaultNotificationsConfig(method) |
| 504 | // Set low lease period to speed up tests. |
| 505 | cfg.LeasePeriod = serpent.Duration(leasePeriod) |
| 506 | cfg.DispatchTimeout = serpent.Duration(leasePeriod - time.Millisecond) |
| 507 | |
| 508 | noopInterceptor := newNoopStoreSyncer(store) |
| 509 | |
| 510 | mgrCtx, cancelManagerCtx := context.WithCancel(dbauthz.AsNotifier(context.Background())) |
| 511 | t.Cleanup(cancelManagerCtx) |
| 512 | |
| 513 | mgr, err := notifications.NewManager(cfg, noopInterceptor, pubsub, defaultHelpers(), createMetrics(), logger.Named("manager")) |
| 514 | require.NoError(t, err) |
| 515 | enq, err := notifications.NewStoreEnqueuer(cfg, store, defaultHelpers(), logger.Named("enqueuer"), quartz.NewReal()) |
| 516 | require.NoError(t, err) |
| 517 | |
| 518 | user := createSampleUser(t, store) |
| 519 | |
| 520 | // WHEN: a few notifications are enqueued which will all succeed |
| 521 | var msgs []string |
| 522 | for i := 0; i < msgCount; i++ { |
| 523 | ids, err := enq.Enqueue(ctx, user.ID, notifications.TemplateWorkspaceDeleted, |
| 524 | map[string]string{"type": "success", "index": fmt.Sprintf("%d", i)}, "test") |
| 525 | require.NoError(t, err) |
| 526 | require.Len(t, ids, 2) |
| 527 | msgs = append(msgs, ids[0].String(), ids[1].String()) |
| 528 | } |
| 529 | |
| 530 | mgr.Run(mgrCtx) |
| 531 | |
| 532 | // THEN: |
| 533 | |
| 534 | // Wait for the messages to be acquired |
| 535 | <-noopInterceptor.acquiredChan |
| 536 | // Then cancel the context, forcing the notification manager to shutdown ungracefully (simulating a crash); leaving messages in "leased" status. |
| 537 | cancelManagerCtx() |
| 538 | |
| 539 | // Fetch any messages currently in "leased" status, and verify that they're exactly the ones we enqueued. |
| 540 | leased, err := store.GetNotificationMessagesByStatus(ctx, database.GetNotificationMessagesByStatusParams{ |
| 541 | Status: database.NotificationMessageStatusLeased, |
| 542 | Limit: msgCount * 2, |
| 543 | }) |
| 544 | require.NoError(t, err) |
| 545 |
nothing calls this directly
no test coverage detected