diff --git a/pkg/kv/kvserver/replica_lease_renewal_test.go b/pkg/kv/kvserver/replica_lease_renewal_test.go index 0064982ed531..fc81564280e7 100644 --- a/pkg/kv/kvserver/replica_lease_renewal_test.go +++ b/pkg/kv/kvserver/replica_lease_renewal_test.go @@ -36,7 +36,10 @@ func TestLeaseRenewer(t *testing.T) { defer leaktest.AfterTest(t)() defer log.Scope(t).Close(t) - skip.WithIssue(t, 100689) + // stressrace and deadlock make the test too slow, resulting in an inability + // to maintain leases and Raft leadership. + skip.UnderStressRace(t) + skip.UnderDeadlock(t) // When kv.expiration_leases_only.enabled is true, the Raft scheduler is // responsible for extensions, but we still track expiration leases for system @@ -48,9 +51,18 @@ func TestLeaseRenewer(t *testing.T) { tc := serverutils.StartNewTestCluster(t, 3, base.TestClusterArgs{ ServerArgs: base.TestServerArgs{ Settings: st, + // Speed up lease extensions to speed up the test, but adjust tick-based + // timeouts to retain their default wall-time values. RaftConfig: base.RaftConfig{ - RangeLeaseDuration: time.Second, - RaftTickInterval: 100 * time.Millisecond, + RangeLeaseRenewalFraction: 0.95, + RaftTickInterval: 100 * time.Millisecond, + RaftElectionTimeoutTicks: 20, + RaftReproposalTimeoutTicks: 30, + }, + Knobs: base.TestingKnobs{ + Store: &StoreTestingKnobs{ + LeaseRenewalDurationOverride: 100 * time.Millisecond, + }, }, }, }) @@ -173,7 +185,8 @@ func TestLeaseRenewer(t *testing.T) { assertStoreLeaseRenewer(desc.RangeID) // Transfer the lease to a different leaseholder, and assert that the lease is - // still extended. + // still extended. Wait for the split to apply on all nodes first. + require.NoError(t, tc.WaitForFullReplication()) lease, _ := getNodeReplica(1, desc.RangeID).GetLease() target := tc.Target(lookupNode(lease.Replica.NodeID%3 + 1)) tc.TransferRangeLeaseOrFatal(t, desc, target) diff --git a/pkg/kv/kvserver/replica_proposal.go b/pkg/kv/kvserver/replica_proposal.go index 880767b32994..cdc1a19cf712 100644 --- a/pkg/kv/kvserver/replica_proposal.go +++ b/pkg/kv/kvserver/replica_proposal.go @@ -372,8 +372,8 @@ func (r *Replica) leasePostApplyLocked( r.gossipFirstRangeLocked(ctx) } - if newLease.Type() == roachpb.LeaseExpiration && (leaseChangingHands || maybeSplit) && - iAmTheLeaseHolder && r.ownsValidLeaseRLocked(ctx, now) { + isExpirationLease := newLease.Type() == roachpb.LeaseExpiration + if isExpirationLease && (leaseChangingHands || maybeSplit) && iAmTheLeaseHolder { if r.requiresExpirationLeaseRLocked() { // Whenever we first acquire an expiration-based lease for a range that // requires it (i.e. the liveness or meta ranges), notify the lease @@ -388,7 +388,7 @@ func (r *Replica) leasePostApplyLocked( case r.store.renewableLeasesSignal <- struct{}{}: default: } - } else if !r.shouldUseExpirationLeaseRLocked() { + } else if !r.shouldUseExpirationLeaseRLocked() && r.ownsValidLeaseRLocked(ctx, now) { // We received an expiration lease for a range that shouldn't keep using // it, most likely as part of a lease transfer (which is always // expiration-based). We've also applied it before it has expired. Upgrade diff --git a/pkg/ui/workspaces/cluster-ui/src/sqlActivity/util.tsx b/pkg/ui/workspaces/cluster-ui/src/sqlActivity/util.tsx index d770226c812a..748a13db2d61 100644 --- a/pkg/ui/workspaces/cluster-ui/src/sqlActivity/util.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/sqlActivity/util.tsx @@ -43,10 +43,18 @@ export function filteredStatementsData( // Current filters: search text, database, fullScan, service latency, // SQL Type, nodes and regions. return statements - .filter( - statement => - databases.length == 0 || databases.includes(statement.database), - ) + .filter(statement => { + try { + // Case where the database is returned as an array in a string form. + const dbList = JSON.parse(statement.database); + return ( + databases.length === 0 || databases.some(d => dbList.includes(d)) + ); + } catch (e) { + // Case where the database is a single value as a string. + return databases.length === 0 || databases.includes(statement.database); + } + }) .filter(statement => (filters.fullScan ? statement.fullScan : true)) .filter( statement => diff --git a/pkg/ui/workspaces/cluster-ui/src/statementsTable/statementsTable.tsx b/pkg/ui/workspaces/cluster-ui/src/statementsTable/statementsTable.tsx index f772d2e9f052..b7f4e111e006 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementsTable/statementsTable.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/statementsTable/statementsTable.tsx @@ -101,6 +101,16 @@ export function shortStatement( } } +function formatStringArray(databases: string): string { + try { + // Case where the database is returned as an array in a string form. + return JSON.parse(databases).join(", "); + } catch (e) { + // Case where the database is a single value as a string. + return databases; + } +} + export function makeStatementsColumns( statements: AggregateStatistics[], selectedApps: string[], @@ -173,7 +183,7 @@ export function makeStatementsColumns( name: "database", title: statisticsTableTitles.database(statType), className: cx("statements-table__col-database"), - cell: (stmt: AggregateStatistics) => stmt.database, + cell: (stmt: AggregateStatistics) => formatStringArray(stmt.database), sort: (stmt: AggregateStatistics) => stmt.database, showByDefault: false, },