github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/txnutil/gc/gc_service_test.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package gc 15 16 import ( 17 "context" 18 "math" 19 "testing" 20 21 "github.com/pingcap/errors" 22 "github.com/pingcap/tiflow/cdc/model" 23 "github.com/stretchr/testify/require" 24 pd "github.com/tikv/pd/client" 25 ) 26 27 func TestCheckSafetyOfStartTs(t *testing.T) { 28 t.Parallel() 29 30 pdCli := &mockPdClientForServiceGCSafePoint{serviceSafePoint: make(map[string]uint64)} 31 32 ctx := context.Background() 33 34 TTL := int64(1) 35 // assume no pd leader switch 36 pdCli.UpdateServiceGCSafePoint(ctx, "service1", 10, 60) //nolint:errcheck 37 err := EnsureChangefeedStartTsSafety(ctx, pdCli, 38 "ticdc-creating-", 39 model.DefaultChangeFeedID("changefeed1"), TTL, 50) 40 require.Equal(t, 41 "[CDC:ErrStartTsBeforeGC]fail to create or maintain changefeed "+ 42 "because start-ts 50 is earlier than or equal to GC safepoint at 60", err.Error()) 43 pdCli.UpdateServiceGCSafePoint(ctx, "service2", 10, 80) //nolint:errcheck 44 pdCli.UpdateServiceGCSafePoint(ctx, "service3", 10, 70) //nolint:errcheck 45 err = EnsureChangefeedStartTsSafety(ctx, pdCli, 46 "ticdc-creating-", 47 model.DefaultChangeFeedID("changefeed2"), TTL, 65) 48 require.Nil(t, err) 49 require.Equal(t, pdCli.serviceSafePoint, map[string]uint64{ 50 "service1": 60, 51 "service2": 80, 52 "service3": 70, 53 "ticdc-creating-default_changefeed2": 65, 54 }) 55 err = UndoEnsureChangefeedStartTsSafety(ctx, pdCli, 56 "ticdc-creating-", 57 model.DefaultChangeFeedID("changefeed2")) 58 require.Nil(t, err) 59 require.Equal(t, pdCli.serviceSafePoint, map[string]uint64{ 60 "service1": 60, 61 "service2": 80, 62 "service3": 70, 63 "ticdc-creating-default_changefeed2": math.MaxUint64, 64 }) 65 66 pdCli.enableLeaderSwitch = true 67 68 pdCli.retryThreshold = 1 69 pdCli.retryCount = 0 70 err = EnsureChangefeedStartTsSafety(ctx, pdCli, 71 "ticdc-creating-", 72 model.DefaultChangeFeedID("changefeed2"), TTL, 65) 73 require.Nil(t, err) 74 75 pdCli.retryThreshold = gcServiceMaxRetries + 1 76 pdCli.retryCount = 0 77 err = EnsureChangefeedStartTsSafety(ctx, pdCli, 78 "ticdc-creating-", 79 model.DefaultChangeFeedID("changefeed2"), TTL, 65) 80 require.NotNil(t, err) 81 require.Equal(t, err.Error(), 82 "[CDC:ErrReachMaxTry]reach maximum try: 9, error: not pd leader: not pd leader") 83 84 pdCli.retryThreshold = 3 85 pdCli.retryCount = 0 86 err = EnsureChangefeedStartTsSafety(ctx, pdCli, 87 "ticdc-creating-", 88 model.DefaultChangeFeedID("changefeed1"), TTL, 50) 89 require.Equal(t, err.Error(), 90 "[CDC:ErrStartTsBeforeGC]fail to create or maintain changefeed "+ 91 "because start-ts 50 is earlier than or equal to GC safepoint at 60") 92 } 93 94 type mockPdClientForServiceGCSafePoint struct { 95 pd.Client 96 serviceSafePoint map[string]uint64 97 enableLeaderSwitch bool 98 retryCount int 99 retryThreshold int 100 } 101 102 func (m *mockPdClientForServiceGCSafePoint) UpdateServiceGCSafePoint(ctx context.Context, serviceID string, ttl int64, safePoint uint64) (uint64, error) { 103 defer func() { m.retryCount++ }() 104 minSafePoint := uint64(math.MaxUint64) 105 if m.enableLeaderSwitch && m.retryCount < m.retryThreshold { 106 // simulate pd leader switch error 107 return minSafePoint, errors.New("not pd leader") 108 } 109 110 for _, safePoint := range m.serviceSafePoint { 111 if minSafePoint > safePoint { 112 minSafePoint = safePoint 113 } 114 } 115 if safePoint < minSafePoint && len(m.serviceSafePoint) != 0 { 116 return minSafePoint, nil 117 } 118 m.serviceSafePoint[serviceID] = safePoint 119 return minSafePoint, nil 120 }