github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/protectedts/ptreconcile/reconciler_test.go (about) 1 // Copyright 2020 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package ptreconcile_test 12 13 import ( 14 "context" 15 "testing" 16 "time" 17 18 "github.com/cockroachdb/cockroach/pkg/base" 19 "github.com/cockroachdb/cockroach/pkg/keys" 20 "github.com/cockroachdb/cockroach/pkg/kv" 21 "github.com/cockroachdb/cockroach/pkg/kv/kvserver" 22 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/protectedts" 23 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/protectedts/ptpb" 24 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/protectedts/ptreconcile" 25 "github.com/cockroachdb/cockroach/pkg/roachpb" 26 "github.com/cockroachdb/cockroach/pkg/settings/cluster" 27 "github.com/cockroachdb/cockroach/pkg/sql" 28 "github.com/cockroachdb/cockroach/pkg/testutils" 29 "github.com/cockroachdb/cockroach/pkg/testutils/testcluster" 30 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 31 "github.com/cockroachdb/cockroach/pkg/util/syncutil" 32 "github.com/cockroachdb/cockroach/pkg/util/uuid" 33 "github.com/cockroachdb/errors" 34 "github.com/stretchr/testify/require" 35 ) 36 37 func TestReconciler(t *testing.T) { 38 defer leaktest.AfterTest(t)() 39 40 ctx := context.Background() 41 tc := testcluster.StartTestCluster(t, 1, base.TestClusterArgs{}) 42 defer tc.Stopper().Stop(ctx) 43 44 // Now I want to create some artifacts that should get reconciled away and 45 // then make sure that they do and others which should not do not. 46 s0 := tc.Server(0) 47 ptp := s0.ExecutorConfig().(sql.ExecutorConfig).ProtectedTimestampProvider 48 49 settings := cluster.MakeTestingClusterSettings() 50 const testTaskType = "foo" 51 var state = struct { 52 mu syncutil.Mutex 53 toRemove map[string]struct{} 54 }{} 55 state.toRemove = map[string]struct{}{} 56 cfg := ptreconcile.Config{ 57 Settings: settings, 58 Stores: s0.GetStores().(*kvserver.Stores), 59 DB: s0.DB(), 60 Storage: ptp, 61 Cache: ptp, 62 StatusFuncs: ptreconcile.StatusFuncs{ 63 testTaskType: func( 64 ctx context.Context, txn *kv.Txn, meta []byte, 65 ) (shouldRemove bool, err error) { 66 state.mu.Lock() 67 defer state.mu.Unlock() 68 _, shouldRemove = state.toRemove[string(meta)] 69 return shouldRemove, nil 70 }, 71 }, 72 } 73 r := ptreconcile.NewReconciler(cfg) 74 require.NoError(t, r.Start(ctx, tc.Stopper())) 75 recMeta := "a" 76 rec1 := ptpb.Record{ 77 ID: uuid.MakeV4(), 78 Timestamp: s0.Clock().Now(), 79 Mode: ptpb.PROTECT_AFTER, 80 MetaType: testTaskType, 81 Meta: []byte(recMeta), 82 Spans: []roachpb.Span{ 83 {Key: keys.MinKey, EndKey: keys.MaxKey}, 84 }, 85 } 86 require.NoError(t, s0.DB().Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { 87 return ptp.Protect(ctx, txn, &rec1) 88 })) 89 90 t.Run("update settings", func(t *testing.T) { 91 ptreconcile.ReconcileInterval.Override(&settings.SV, time.Millisecond) 92 testutils.SucceedsSoon(t, func() error { 93 require.Equal(t, int64(0), r.Metrics().RecordsRemoved.Count()) 94 require.Equal(t, int64(0), r.Metrics().ReconciliationErrors.Count()) 95 if processed := r.Metrics().RecordsProcessed.Count(); processed < 1 { 96 return errors.Errorf("expected processed to be at least 1, got %d", processed) 97 } 98 return nil 99 }) 100 }) 101 t.Run("reconcile", func(t *testing.T) { 102 state.mu.Lock() 103 state.toRemove[recMeta] = struct{}{} 104 state.mu.Unlock() 105 106 ptreconcile.ReconcileInterval.Override(&settings.SV, time.Millisecond) 107 testutils.SucceedsSoon(t, func() error { 108 require.Equal(t, int64(0), r.Metrics().ReconciliationErrors.Count()) 109 if removed := r.Metrics().RecordsRemoved.Count(); removed != 1 { 110 return errors.Errorf("expected processed to be 1, got %d", removed) 111 } 112 return nil 113 }) 114 require.Regexp(t, protectedts.ErrNotExists, s0.DB().Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { 115 _, err := ptp.GetRecord(ctx, txn, rec1.ID) 116 return err 117 })) 118 }) 119 }