@@ -11703,3 +11703,83 @@ func TestCloudstorageParallelCompression(t *testing.T) {
11703
11703
}
11704
11704
})
11705
11705
}
11706
+
11707
+ // TestChangefeedResumeWithBothLegacyAndCurrentCheckpoint is a regression
11708
+ // test for #148620, which was a bug where the legacy checkpoint was not
11709
+ // being cleared after the cluster was upgraded to 25.2 and subsequently
11710
+ // causing an assertion error when resuming.
11711
+ func TestChangefeedResumeWithBothLegacyAndCurrentCheckpoint (t * testing.T ) {
11712
+ defer leaktest .AfterTest (t )()
11713
+ defer log .Scope (t ).Close (t )
11714
+
11715
+ testFn := func (t * testing.T , s TestServer , f cdctest.TestFeedFactory ) {
11716
+ ctx := context .Background ()
11717
+ sqlDB := sqlutils .MakeSQLRunner (s .DB )
11718
+
11719
+ // Create a table with 11 ranges.
11720
+ const numRows = 10
11721
+ const numRanges = numRows + 1
11722
+ sqlDB .ExecMultiple (t ,
11723
+ `CREATE TABLE foo (a INT PRIMARY KEY)` ,
11724
+ fmt .Sprintf (`INSERT INTO foo SELECT * FROM generate_series(1, %d)` , numRows ),
11725
+ fmt .Sprintf (`ALTER TABLE foo SPLIT AT (SELECT * FROM generate_series(1, %d))` , numRows ),
11726
+ )
11727
+ fooSpan := desctestutils .
11728
+ TestingGetPublicTableDescriptor (s .Server .DB (), s .Codec , "d" , "foo" ).
11729
+ PrimaryIndexSpan (s .Codec )
11730
+ ranges , _ , err := s .Server .
11731
+ DistSenderI ().(* kvcoord.DistSender ).
11732
+ AllRangeSpans (ctx , []roachpb.Span {fooSpan })
11733
+ require .NoError (t , err )
11734
+ require .Len (t , ranges , numRanges )
11735
+
11736
+ cf := feed (t , f , `CREATE CHANGEFEED FOR foo WITH no_initial_scan` )
11737
+ defer closeFeed (t , cf )
11738
+
11739
+ jobFeed , ok := cf .(cdctest.EnterpriseTestFeed )
11740
+ require .True (t , ok )
11741
+
11742
+ sqlDB .Exec (t , `PAUSE JOB $1` , jobFeed .JobID ())
11743
+ waitForJobState (sqlDB , t , jobFeed .JobID (), jobs .StatePaused )
11744
+ hw , err := jobFeed .HighWaterMark ()
11745
+ require .NoError (t , err )
11746
+
11747
+ registry := s .Server .JobRegistry ().(* jobs.Registry )
11748
+
11749
+ // Manually insert both a legacy and current checkpoint containing
11750
+ // a random range from the table.
11751
+ rnd , _ := randutil .NewTestRand ()
11752
+ randomRange := ranges [rnd .Intn (len (ranges ))]
11753
+ err = registry .UpdateJobWithTxn (ctx , jobFeed .JobID (), nil ,
11754
+ func (txn isql.Txn , md jobs.JobMetadata , ju * jobs.JobUpdater ) error {
11755
+ checkpointTS := hw .Add (int64 (time .Nanosecond ), 0 )
11756
+ progress := md .Progress
11757
+ progress .Details = jobspb .WrapProgressDetails (jobspb.ChangefeedProgress {
11758
+ //lint:ignore SA1019 deprecated usage
11759
+ Checkpoint : & jobspb.ChangefeedProgress_Checkpoint {
11760
+ Spans : []roachpb.Span {randomRange },
11761
+ Timestamp : checkpointTS ,
11762
+ },
11763
+ SpanLevelCheckpoint : jobspb .NewTimestampSpansMap (
11764
+ map [hlc.Timestamp ]roachpb.Spans {
11765
+ checkpointTS : []roachpb.Span {randomRange },
11766
+ },
11767
+ ),
11768
+ })
11769
+ ju .UpdateProgress (progress )
11770
+ return nil
11771
+ })
11772
+ require .NoError (t , err )
11773
+
11774
+ sqlDB .Exec (t , `RESUME JOB $1` , jobFeed .JobID ())
11775
+ waitForJobState (sqlDB , t , jobFeed .JobID (), jobs .StateRunning )
11776
+
11777
+ // Wait for highwater to advance past the current time.
11778
+ var tsStr string
11779
+ sqlDB .QueryRow (t , `SELECT cluster_logical_timestamp()` ).Scan (& tsStr )
11780
+ ts := parseTimeToHLC (t , tsStr )
11781
+ require .NoError (t , jobFeed .WaitForHighWaterMark (ts ))
11782
+ }
11783
+
11784
+ cdcTest (t , testFn , feedTestEnterpriseSinks )
11785
+ }
0 commit comments