github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/txnutil/gc/gc_manager_test.go (about) 1 // Copyright 2021 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 "testing" 19 "time" 20 21 "github.com/pingcap/errors" 22 "github.com/pingcap/tiflow/cdc/model" 23 cerror "github.com/pingcap/tiflow/pkg/errors" 24 "github.com/pingcap/tiflow/pkg/etcd" 25 "github.com/pingcap/tiflow/pkg/pdutil" 26 "github.com/stretchr/testify/require" 27 "github.com/tikv/client-go/v2/oracle" 28 ) 29 30 func TestUpdateGCSafePoint(t *testing.T) { 31 t.Parallel() 32 33 mockPDClient := &MockPDClient{} 34 pdClock := pdutil.NewClock4Test() 35 gcManager := NewManager(etcd.GcServiceIDForTest(), 36 mockPDClient, pdClock).(*gcManager) 37 ctx := context.Background() 38 39 startTs := oracle.GoTimeToTS(time.Now()) 40 mockPDClient.UpdateServiceGCSafePointFunc = func(ctx context.Context, serviceID string, ttl int64, safePoint uint64) (uint64, error) { 41 require.Equal(t, startTs, safePoint) 42 require.Equal(t, gcManager.gcTTL, ttl) 43 require.Equal(t, etcd.GcServiceIDForTest(), serviceID) 44 return 0, nil 45 } 46 err := gcManager.TryUpdateGCSafePoint(ctx, startTs, false /* forceUpdate */) 47 require.Nil(t, err) 48 49 // gcManager must not update frequent. 50 gcManager.lastUpdatedTime = time.Now() 51 startTs++ 52 err = gcManager.TryUpdateGCSafePoint(ctx, startTs, false /* forceUpdate */) 53 require.Nil(t, err) 54 55 // Assume that the gc safe point updated gcSafepointUpdateInterval ago. 56 gcManager.lastUpdatedTime = time.Now().Add(-gcSafepointUpdateInterval) 57 startTs++ 58 mockPDClient.UpdateServiceGCSafePointFunc = func(ctx context.Context, serviceID string, ttl int64, safePoint uint64) (uint64, error) { 59 require.Equal(t, startTs, safePoint) 60 require.Equal(t, gcManager.gcTTL, ttl) 61 require.Equal(t, etcd.GcServiceIDForTest(), serviceID) 62 return 0, nil 63 } 64 err = gcManager.TryUpdateGCSafePoint(ctx, startTs, false /* forceUpdate */) 65 require.Nil(t, err) 66 67 // Force update 68 startTs++ 69 ch := make(chan struct{}, 1) 70 mockPDClient.UpdateServiceGCSafePointFunc = func(ctx context.Context, serviceID string, ttl int64, safePoint uint64) (uint64, error) { 71 require.Equal(t, startTs, safePoint) 72 require.Equal(t, gcManager.gcTTL, ttl) 73 require.Equal(t, etcd.GcServiceIDForTest(), serviceID) 74 ch <- struct{}{} 75 return 0, nil 76 } 77 err = gcManager.TryUpdateGCSafePoint(ctx, startTs, true /* forceUpdate */) 78 require.Nil(t, err) 79 select { 80 case <-time.After(5 * time.Second): 81 t.Fatal("timeout") 82 case <-ch: 83 } 84 } 85 86 func TestCheckStaleCheckpointTs(t *testing.T) { 87 t.Parallel() 88 89 mockPDClient := &MockPDClient{} 90 pdClock := pdutil.NewClock4Test() 91 gcManager := NewManager(etcd.GcServiceIDForTest(), 92 mockPDClient, pdClock).(*gcManager) 93 ctx := context.Background() 94 95 time.Sleep(1 * time.Second) 96 97 cfID := model.DefaultChangeFeedID("cfID") 98 err := gcManager.CheckStaleCheckpointTs(ctx, cfID, oracle.GoTimeToTS(time.Now())) 99 require.Nil(t, err) 100 101 gcManager.lastSafePointTs.Store(20) 102 err = gcManager.CheckStaleCheckpointTs(ctx, cfID, 10) 103 require.True(t, cerror.ErrSnapshotLostByGC.Equal(errors.Cause(err))) 104 require.True(t, cerror.IsChangefeedGCFastFailError(err)) 105 }