(t *testing.T)
| 494 | } |
| 495 | |
| 496 | func TestWorker_UpsertError_ContinuesNextRow(t *testing.T) { |
| 497 | t.Parallel() |
| 498 | ctx := testutil.Context(t, testutil.WaitShort) |
| 499 | |
| 500 | chat1 := uuid.New() |
| 501 | chat2 := uuid.New() |
| 502 | ownerID := uuid.New() |
| 503 | |
| 504 | var publishCount atomic.Int32 |
| 505 | tickDone := make(chan struct{}) |
| 506 | var closeOnce sync.Once |
| 507 | var mu sync.Mutex |
| 508 | upsertedChatIDs := make(map[uuid.UUID]struct{}) |
| 509 | |
| 510 | // We have 2 rows. The upsert for chat1 fails; the upsert |
| 511 | // for chat2 succeeds and publishes. Because goroutines run |
| 512 | // concurrently we don't know which finishes last, so we |
| 513 | // track the total number of "terminal" events (upsert error |
| 514 | // + publish success) and close tickDone when both have |
| 515 | // occurred. |
| 516 | var terminalOps atomic.Int32 |
| 517 | signalIfDone := func() { |
| 518 | if terminalOps.Add(1) == 2 { |
| 519 | closeOnce.Do(func() { close(tickDone) }) |
| 520 | } |
| 521 | } |
| 522 | |
| 523 | ctrl := gomock.NewController(t) |
| 524 | store := dbmock.NewMockStore(ctrl) |
| 525 | |
| 526 | store.EXPECT().AcquireStaleChatDiffStatuses(gomock.Any(), gomock.Any()). |
| 527 | Return([]database.AcquireStaleChatDiffStatusesRow{ |
| 528 | makeAcquiredRowWithBranch(chat1, ownerID, "feature"), |
| 529 | makeAcquiredRowWithBranch(chat2, ownerID, "feature"), |
| 530 | }, nil) |
| 531 | store.EXPECT().UpsertChatDiffStatus(gomock.Any(), gomock.Any()). |
| 532 | DoAndReturn(func(_ context.Context, arg database.UpsertChatDiffStatusParams) (database.ChatDiffStatus, error) { |
| 533 | if arg.ChatID == chat1 { |
| 534 | // Terminal event for the failing row. |
| 535 | signalIfDone() |
| 536 | return database.ChatDiffStatus{}, fmt.Errorf("db write error") |
| 537 | } |
| 538 | mu.Lock() |
| 539 | upsertedChatIDs[arg.ChatID] = struct{}{} |
| 540 | mu.Unlock() |
| 541 | return database.ChatDiffStatus{ChatID: arg.ChatID}, nil |
| 542 | }).Times(2) |
| 543 | |
| 544 | pub := func(_ context.Context, _ uuid.UUID) error { |
| 545 | publishCount.Add(1) |
| 546 | // Terminal event for the successful row. |
| 547 | signalIfDone() |
| 548 | return nil |
| 549 | } |
| 550 | |
| 551 | mClock := quartz.NewMock(t) |
| 552 | logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}) |
| 553 | refresher := newTestRefresher(t, mClock) |
nothing calls this directly
no test coverage detected