Skip to content

Commit c44ffa8

Browse files
changefeedccl: deflake TestChangefeedSchemaChangeBackfillCheckpoint
Previously, the test `TestChangefeedSchemaChangeBackfillCheckpoint` would fail because it would read a table span too early. A schema change using the delcarative schema changer will update a table span to point to a new set of ranges. Previously, this test would use the span from before the schema change, which is incorrect. This change makes it use the span from after the schema change. I stress tested this 30k times under the new schema changer and 10k times under the legacy schema changer to ensure the test is not flaky anymore. Fixes: cockroachdb#108084 Release note: None Epic: None
1 parent 3e7991d commit c44ffa8

File tree

1 file changed

+34
-19
lines changed

1 file changed

+34
-19
lines changed

pkg/ccl/changefeedccl/changefeed_test.go

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,15 +1944,17 @@ func TestChangefeedSchemaChangeBackfillCheckpoint(t *testing.T) {
19441944
changefeedbase.FrontierCheckpointMaxBytes.Override(
19451945
context.Background(), &s.Server.ClusterSettings().SV, maxCheckpointSize)
19461946

1947-
// Note the tableSpan to avoid resolved events that leave no gaps
1948-
fooDesc := desctestutils.TestingGetPublicTableDescriptor(
1949-
s.SystemServer.DB(), s.Codec, "d", "foo")
1950-
tableSpan := fooDesc.PrimaryIndexSpan(s.Codec)
1947+
var tableSpan roachpb.Span
1948+
refreshTableSpan := func() {
1949+
fooDesc := desctestutils.TestingGetPublicTableDescriptor(
1950+
s.SystemServer.DB(), s.Codec, "d", "foo")
1951+
tableSpan = fooDesc.PrimaryIndexSpan(s.Codec)
1952+
}
19511953

19521954
// FilterSpanWithMutation should ensure that once the backfill begins, the following resolved events
19531955
// that are for that backfill (are of the timestamp right after the backfill timestamp) resolve some
19541956
// but not all of the time, which results in a checkpoint eventually being created
1955-
haveGaps := false
1957+
numGaps := 0
19561958
var backfillTimestamp hlc.Timestamp
19571959
var initialCheckpoint roachpb.SpanGroup
19581960
var foundCheckpoint int32
@@ -1966,6 +1968,11 @@ func TestChangefeedSchemaChangeBackfillCheckpoint(t *testing.T) {
19661968
// timestamp such that all backfill spans have a timestamp of
19671969
// timestamp.Next().
19681970
if r.BoundaryType == expectedBoundaryType {
1971+
// NB: We wait until the schema change is public before looking
1972+
// up the table span. When using the declarative schema changer,
1973+
// the table span will be different before and after the schema
1974+
// change due to a primary index swap.
1975+
refreshTableSpan()
19691976
backfillTimestamp = r.Timestamp
19701977
return false, nil
19711978
}
@@ -1988,11 +1995,18 @@ func TestChangefeedSchemaChangeBackfillCheckpoint(t *testing.T) {
19881995
return !(backfillTimestamp.IsEmpty() || r.Timestamp.LessEq(backfillTimestamp.Next())), nil
19891996
}
19901997

1991-
// Only allow resolving if we definitely won't have a completely resolved table
1992-
if !r.Span.Equal(tableSpan) && haveGaps {
1998+
// At the end of a backfill, kv feed will emit a resolved span for the whole table.
1999+
// Filter this out because we would like to leave gaps.
2000+
if r.Span.Equal(tableSpan) {
2001+
return true, nil
2002+
}
2003+
2004+
// Ensure that we have at least 2 gaps, so when a second checkpoint happens later in this test,
2005+
// the second checkpoint can still leave at least one gap.
2006+
if numGaps >= 2 {
19932007
return rnd.Intn(10) > 7, nil
19942008
}
1995-
haveGaps = true
2009+
numGaps += 1
19962010
return true, nil
19972011
}
19982012

@@ -2021,7 +2035,7 @@ func TestChangefeedSchemaChangeBackfillCheckpoint(t *testing.T) {
20212035
// as well as the newly resolved ones
20222036
var secondCheckpoint roachpb.SpanGroup
20232037
foundCheckpoint = 0
2024-
haveGaps = false
2038+
numGaps = 0
20252039
knobs.FilterSpanWithMutation = func(r *jobspb.ResolvedSpan) (bool, error) {
20262040
// Stop resolving anything after second checkpoint set to avoid backfill completion
20272041
if secondCheckpoint.Len() > 0 {
@@ -2049,11 +2063,17 @@ func TestChangefeedSchemaChangeBackfillCheckpoint(t *testing.T) {
20492063

20502064
require.Falsef(t, initialCheckpoint.Encloses(r.Span), "second backfill should not resolve checkpointed span")
20512065

2052-
// Only allow resolving if we definitely won't have a completely resolved table
2053-
if !r.Span.Equal(tableSpan) && haveGaps {
2066+
// At the end of a backfill, kv feed will emit a resolved span for the whole table.
2067+
// Filter this out because we would like to leave at least one gap.
2068+
if r.Span.Equal(tableSpan) {
2069+
return true, nil
2070+
}
2071+
2072+
// Ensure there is at least one gap so that we can receive resolved spans later.
2073+
if numGaps >= 1 {
20542074
return rnd.Intn(10) > 7, nil
20552075
}
2056-
haveGaps = true
2076+
numGaps += 1
20572077
return true, nil
20582078
}
20592079

@@ -2092,15 +2112,10 @@ func TestChangefeedSchemaChangeBackfillCheckpoint(t *testing.T) {
20922112
// Pause job to avoid race on the resolved array
20932113
require.NoError(t, jobFeed.Pause())
20942114

2095-
// NB: With the declarative schema changer, there is a primary index swap,
2096-
// so the primary index span will change.
2097-
freshFooDesc := desctestutils.TestingGetPublicTableDescriptor(
2098-
s.SystemServer.DB(), s.Codec, "d", "foo")
2099-
tableSpanAfter := freshFooDesc.PrimaryIndexSpan(s.Codec)
2100-
21012115
// Verify that none of the resolved spans after resume were checkpointed.
2116+
t.Logf("Table Span: %s, Second Checkpoint: %v, Resolved Spans: %v", tableSpan, secondCheckpoint, resolved)
21022117
for _, sp := range resolved {
2103-
require.Falsef(t, !sp.Equal(tableSpanAfter) && secondCheckpoint.Contains(sp.Key), "span should not have been resolved: %s", sp)
2118+
require.Falsef(t, !sp.Equal(tableSpan) && secondCheckpoint.Contains(sp.Key), "span should not have been resolved: %s", sp)
21042119
}
21052120
}
21062121

0 commit comments

Comments
 (0)