@@ -1481,6 +1481,50 @@ func TestDebugURLFormatting(t *testing.T) {
1481
1481
require .Contains (t , wr .String (), expectedURL , "output missing formatted URL" )
1482
1482
}
1483
1483
1484
+ // TestConcurrentUpdates tests that concurrent updates from the HealthCheck implementation aren't dropped.
1485
+ // Added in response to https://github.com/vitessio/vitess/issues/17629.
1486
+ func TestConcurrentUpdates (t * testing.T ) {
1487
+ ctx := utils .LeakCheckContext (t )
1488
+ var mu sync.Mutex
1489
+ // reset error counters
1490
+ hcErrorCounters .ResetAll ()
1491
+ ts := memorytopo .NewServer (ctx , "cell" )
1492
+ defer ts .Close ()
1493
+ hc := createTestHc (ctx , ts )
1494
+ // close healthcheck
1495
+ defer hc .Close ()
1496
+
1497
+ // Subscribe to the healthcheck
1498
+ // Make the receiver keep track of the updates received.
1499
+ ch := hc .Subscribe ()
1500
+ totalCount := 0
1501
+ go func () {
1502
+ for range ch {
1503
+ mu .Lock ()
1504
+ totalCount ++
1505
+ mu .Unlock ()
1506
+ // Simulate a somewhat slow consumer.
1507
+ time .Sleep (100 * time .Millisecond )
1508
+ }
1509
+ }()
1510
+
1511
+ // Run multiple updates really quickly
1512
+ // one after the other.
1513
+ totalUpdates := 10
1514
+ for i := 0 ; i < totalUpdates ; i ++ {
1515
+ hc .broadcast (& TabletHealth {})
1516
+ }
1517
+ // Unsubscribe from the healthcheck
1518
+ // and verify we process all the updates eventually.
1519
+ hc .Unsubscribe (ch )
1520
+ defer close (ch )
1521
+ require .Eventuallyf (t , func () bool {
1522
+ mu .Lock ()
1523
+ defer mu .Unlock ()
1524
+ return totalUpdates == totalCount
1525
+ }, 5 * time .Second , 100 * time .Millisecond , "expected all updates to be processed" )
1526
+ }
1527
+
1484
1528
func tabletDialer (tablet * topodatapb.Tablet , _ grpcclient.FailFast ) (queryservice.QueryService , error ) {
1485
1529
connMapMu .Lock ()
1486
1530
defer connMapMu .Unlock ()
0 commit comments