@@ -424,27 +424,114 @@ func TestChangefeedCanceledWhenPTSIsOld(t *testing.T) {
424
424
// single row with multiple versions.
425
425
sqlDB .Exec (t , `CREATE TABLE foo (a INT PRIMARY KEY, b INT)` )
426
426
427
- feed , err := f .Feed ("CREATE CHANGEFEED FOR TABLE foo WITH protect_data_from_gc_on_pause, gc_protect_expires_after='24h'" )
428
- require .NoError (t , err )
429
- defer func () {
430
- closeFeed (t , feed )
431
- }()
427
+ t .Run ("canceled due to gc_protect_expires_after option" , func (t * testing.T ) {
428
+ testutils .RunValues (t , "initially-protected-with" , []string {"none" , "option" , "setting" },
429
+ func (t * testing.T , initialProtect string ) {
430
+ defer func () {
431
+ sqlDB .Exec (t , `RESET CLUSTER SETTING changefeed.protect_timestamp.max_age` )
432
+ }()
433
+
434
+ if initialProtect == "option" {
435
+ // We set the cluster setting to something small to make sure that
436
+ // the option alone is able to protect the PTS record.
437
+ sqlDB .Exec (t , `SET CLUSTER SETTING changefeed.protect_timestamp.max_age = '1us'` )
438
+ } else {
439
+ sqlDB .Exec (t , `SET CLUSTER SETTING changefeed.protect_timestamp.max_age = '24h'` )
440
+ }
432
441
433
- jobFeed := feed .(cdctest.EnterpriseTestFeed )
434
- require .NoError (t , jobFeed .Pause ())
442
+ feedStmt := `CREATE CHANGEFEED FOR TABLE foo`
443
+ switch initialProtect {
444
+ case "none" :
445
+ feedStmt += ` WITH gc_protect_expires_after='1us'`
446
+ case "option" :
447
+ feedStmt += ` WITH gc_protect_expires_after='24h'`
448
+ }
449
+
450
+ feed , err := f .Feed (feedStmt )
451
+ require .NoError (t , err )
452
+ defer func () {
453
+ closeFeed (t , feed )
454
+ }()
435
455
436
- // While the job is paused, take opportunity to test that alter changefeed
437
- // works when setting gc_protect_expires_after option.
456
+ jobFeed := feed .(cdctest.EnterpriseTestFeed )
438
457
439
- // Verify we can set it to 0 -- i.e. disable.
440
- sqlDB .Exec (t , fmt .Sprintf ("ALTER CHANGEFEED %d SET gc_protect_expires_after = '0s'" , jobFeed .JobID ()))
441
- // Now, set it to something very small.
442
- sqlDB .Exec (t , fmt .Sprintf ("ALTER CHANGEFEED %d SET gc_protect_expires_after = '250ms'" , jobFeed .JobID ()))
458
+ if initialProtect != "none" {
459
+ require .NoError (t , jobFeed .Pause ())
460
+
461
+ // Wait a little bit and make sure the job ISN'T canceled.
462
+ require .ErrorContains (t , jobFeed .WaitDurationForState (10 * time .Second , func (s jobs.State ) bool {
463
+ return s == jobs .StateCanceled
464
+ }), `still waiting for job status; current status is "paused"` )
465
+
466
+ if initialProtect == "option" {
467
+ // Set the cluster setting back to something high to make sure the
468
+ // option alone can cause the changefeed to be canceled.
469
+ sqlDB .Exec (t , `SET CLUSTER SETTING changefeed.protect_timestamp.max_age = '24h'` )
470
+ }
471
+
472
+ // Set option to something small so that job will be canceled.
473
+ sqlDB .Exec (t , fmt .Sprintf (`ALTER CHANGEFEED %d SET gc_protect_expires_after = '1us'` , jobFeed .JobID ()))
474
+ }
443
475
444
- // Stale PTS record should trigger job cancellation.
445
- require .NoError (t , jobFeed .WaitForState (func (s jobs.State ) bool {
446
- return s == jobs .StateCanceled
447
- }))
476
+ // Stale PTS record should trigger job cancellation.
477
+ require .NoError (t , jobFeed .WaitForState (func (s jobs.State ) bool {
478
+ return s == jobs .StateCanceled
479
+ }))
480
+ })
481
+ })
482
+
483
+ t .Run ("canceled due to changefeed.protect_timestamp.max_age setting" , func (t * testing.T ) {
484
+ testutils .RunValues (t , "initially-protected-with" , []string {"none" , "option" , "setting" },
485
+ func (t * testing.T , initialProtect string ) {
486
+ defer func () {
487
+ sqlDB .Exec (t , `RESET CLUSTER SETTING changefeed.protect_timestamp.max_age` )
488
+ }()
489
+
490
+ if initialProtect == "setting" {
491
+ sqlDB .Exec (t , `SET CLUSTER SETTING changefeed.protect_timestamp.max_age = '24h'` )
492
+ } else {
493
+ sqlDB .Exec (t , `SET CLUSTER SETTING changefeed.protect_timestamp.max_age = '1us'` )
494
+ }
495
+
496
+ // Set the max age cluster setting to something small.
497
+ feedStmt := `CREATE CHANGEFEED FOR TABLE foo`
498
+ if initialProtect == "option" {
499
+ feedStmt += ` WITH gc_protect_expires_after='24h'`
500
+ }
501
+ feed , err := f .Feed (feedStmt )
502
+ require .NoError (t , err )
503
+ defer func () {
504
+ closeFeed (t , feed )
505
+ }()
506
+
507
+ jobFeed := feed .(cdctest.EnterpriseTestFeed )
508
+
509
+ if initialProtect != "none" {
510
+ require .NoError (t , jobFeed .Pause ())
511
+
512
+ // Wait a little bit and make sure the job ISN'T canceled.
513
+ require .ErrorContains (t , jobFeed .WaitDurationForState (10 * time .Second , func (s jobs.State ) bool {
514
+ return s == jobs .StateCanceled
515
+ }), `still waiting for job status; current status is "paused"` )
516
+
517
+ switch initialProtect {
518
+ case "option" :
519
+ // Reset the option so that it defaults to the cluster setting.
520
+ sqlDB .Exec (t , fmt .Sprintf (`ALTER CHANGEFEED %d SET gc_protect_expires_after = '0s'` , jobFeed .JobID ()))
521
+ case "setting" :
522
+ // Modify the cluster setting and do an ALTER CHANGEFEED so that
523
+ // the new value is picked up.
524
+ sqlDB .Exec (t , `SET CLUSTER SETTING changefeed.protect_timestamp.max_age = '1us'` )
525
+ sqlDB .Exec (t , fmt .Sprintf (`ALTER CHANGEFEED %d SET diff` , jobFeed .JobID ()))
526
+ }
527
+ }
528
+
529
+ // Stale PTS record should trigger job cancellation.
530
+ require .NoError (t , jobFeed .WaitForState (func (s jobs.State ) bool {
531
+ return s == jobs .StateCanceled
532
+ }))
533
+ })
534
+ })
448
535
}
449
536
450
537
cdcTestWithSystem (t , testFn , feedTestEnterpriseSinks )
0 commit comments