func (r *Replica) leasePostApply( ctx context.Context, newLease *roachpb.Lease, replicaID roachpb.ReplicaID, prevLease *roachpb.Lease, ) { iAmTheLeaseHolder := newLease.Replica.ReplicaID == replicaID leaseChangingHands := prevLease.Replica.StoreID != newLease.Replica.StoreID if leaseChangingHands && iAmTheLeaseHolder { // If this replica is a new holder of the lease, update the low water // mark of the timestamp cache. Note that clock offset scenarios are // handled via a stasis period inherent in the lease which is documented // in on the Lease struct. // // The introduction of lease transfers implies that the previous lease // may have been shortened and we are now applying a formally overlapping // lease (since the old lease holder has promised not to serve any more // requests, this is kosher). This means that we don't use the old // lease's expiration but instead use the new lease's start to initialize // the timestamp cache low water. if log.V(1) { log.Infof(ctx, "new range lease %s following %s [physicalTime=%s]", newLease, prevLease, r.store.Clock().PhysicalTime()) } r.mu.Lock() r.mu.tsCache.SetLowWater(newLease.Start) r.mu.Unlock() // Gossip the first range whenever its lease is acquired. We check to // make sure the lease is active so that a trailing replica won't process // an old lease request and attempt to gossip the first range. if r.IsFirstRange() && r.IsLeaseValid(newLease, r.store.Clock().Now()) { r.gossipFirstRange(ctx) } } if leaseChangingHands && !iAmTheLeaseHolder { // We're not the lease holder, reset our timestamp cache, releasing // anything currently cached. The timestamp cache is only used by the // lease holder. Note that we'll call SetLowWater when we next acquire // the lease. r.mu.Lock() r.mu.tsCache.Clear(r.store.Clock().Now()) r.mu.Unlock() } if !iAmTheLeaseHolder && r.IsLeaseValid(newLease, r.store.Clock().Now()) { // If this replica is the raft leader but it is not the new lease holder, // then try to transfer the raft leadership to match the lease. We like it // when leases and raft leadership are collocated because that facilitates // quick command application (requests generally need to make it to both the // lease holder and the raft leader before being applied by other replicas). // Note that this condition is also checked periodically when computing // replica metrics. r.maybeTransferRaftLeadership(ctx, newLease.Replica.ReplicaID) } // Notify the store that a lease change occurred and it may need to // gossip the updated store descriptor (with updated capacity). if leaseChangingHands && (prevLease.OwnedBy(r.store.StoreID()) || newLease.OwnedBy(r.store.StoreID())) { r.store.maybeGossipOnCapacityChange(ctx, leaseChangeEvent) } }