github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/jobs/jobsprotectedts/jobs_protected_ts_test.go (about) 1 // Copyright 2017 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 jobsprotectedts_test 12 13 import ( 14 "context" 15 "fmt" 16 "io" 17 "testing" 18 19 "github.com/cockroachdb/cockroach/pkg/base" 20 "github.com/cockroachdb/cockroach/pkg/jobs" 21 "github.com/cockroachdb/cockroach/pkg/jobs/jobspb" 22 "github.com/cockroachdb/cockroach/pkg/jobs/jobsprotectedts" 23 "github.com/cockroachdb/cockroach/pkg/keys" 24 "github.com/cockroachdb/cockroach/pkg/kv" 25 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/protectedts" 26 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/protectedts/ptpb" 27 "github.com/cockroachdb/cockroach/pkg/roachpb" 28 "github.com/cockroachdb/cockroach/pkg/sql" 29 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 30 "github.com/cockroachdb/cockroach/pkg/testutils" 31 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" 32 "github.com/cockroachdb/cockroach/pkg/testutils/testcluster" 33 "github.com/cockroachdb/cockroach/pkg/util/leaktest" 34 "github.com/cockroachdb/cockroach/pkg/util/uuid" 35 "github.com/cockroachdb/errors" 36 "github.com/stretchr/testify/require" 37 ) 38 39 // TestJobsProtectedTimestamp is an end-to-end test of protected timestamp 40 // reconciliation for jobs. 41 func TestJobsProtectedTimestamp(t *testing.T) { 42 defer leaktest.AfterTest(t)() 43 44 ctx := context.Background() 45 tc := testcluster.StartTestCluster(t, 1, base.TestClusterArgs{}) 46 defer tc.Stopper().Stop(ctx) 47 48 // Now I want to create some artifacts that should get reconciled away and 49 // then make sure that they do and others which should not do not. 50 s0 := tc.Server(0) 51 ptp := s0.ExecutorConfig().(sql.ExecutorConfig).ProtectedTimestampProvider 52 runner := sqlutils.MakeSQLRunner(tc.ServerConn(0)) 53 runner.Exec(t, "SET CLUSTER SETTING kv.protectedts.reconciliation.interval = '1ms';") 54 jr := s0.JobRegistry().(*jobs.Registry) 55 mkJobRec := func() jobs.Record { 56 return jobs.Record{ 57 Description: "testing", 58 Statement: "SELECT 1", 59 Username: "root", 60 Details: jobspb.SchemaChangeGCDetails{ 61 Tables: []jobspb.SchemaChangeGCDetails_DroppedID{ 62 { 63 ID: 42, 64 DropTime: s0.Clock().PhysicalNow(), 65 }, 66 }, 67 }, 68 Progress: jobspb.SchemaChangeGCProgress{}, 69 DescriptorIDs: []sqlbase.ID{42}, 70 } 71 } 72 mkJobAndRecord := func() (j *jobs.Job, rec *ptpb.Record) { 73 ts := s0.Clock().Now() 74 require.NoError(t, s0.DB().Txn(ctx, func(ctx context.Context, txn *kv.Txn) (err error) { 75 if j, err = jr.CreateJobWithTxn(ctx, mkJobRec(), txn); err != nil { 76 return err 77 } 78 rec = jobsprotectedts.MakeRecord(uuid.MakeV4(), *j.ID(), ts, []roachpb.Span{{Key: keys.MinKey, EndKey: keys.MaxKey}}) 79 return ptp.Protect(ctx, txn, rec) 80 })) 81 return j, rec 82 } 83 jMovedToFailed, recMovedToFailed := mkJobAndRecord() 84 require.NoError(t, s0.DB().Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { 85 return jr.Failed(ctx, txn, *jMovedToFailed.ID(), io.ErrUnexpectedEOF) 86 })) 87 jFinished, recFinished := mkJobAndRecord() 88 require.NoError(t, s0.DB().Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { 89 return jr.Succeeded(ctx, txn, *jFinished.ID()) 90 })) 91 _, recRemains := mkJobAndRecord() 92 ensureNotExists := func(ctx context.Context, txn *kv.Txn, ptsID uuid.UUID) (err error) { 93 _, err = ptp.GetRecord(ctx, txn, ptsID) 94 if errors.Is(err, protectedts.ErrNotExists) { 95 return nil 96 } 97 return fmt.Errorf("waiting for %v, got %v", protectedts.ErrNotExists, err) 98 } 99 testutils.SucceedsSoon(t, func() (err error) { 100 return s0.DB().Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { 101 if err := ensureNotExists(ctx, txn, recMovedToFailed.ID); err != nil { 102 return err 103 } 104 if err := ensureNotExists(ctx, txn, recFinished.ID); err != nil { 105 return err 106 } 107 _, err := ptp.GetRecord(ctx, txn, recRemains.ID) 108 require.NoError(t, err) 109 return err 110 }) 111 }) 112 113 // Verify that the two jobs we just observed as removed were recorded in the 114 // metrics. 115 var removed int 116 runner.QueryRow(t, ` 117 SELECT 118 value 119 FROM 120 crdb_internal.node_metrics 121 WHERE 122 name = 'kv.protectedts.reconciliation.records_removed'; 123 `).Scan(&removed) 124 require.Equal(t, 2, removed) 125 }