@@ -1646,6 +1646,63 @@ void TExecutor::ApplyExternalPartSwitch(TPendingPartSwitch &partSwitch) {
1646
1646
}
1647
1647
}
1648
1648
1649
+ void TExecutor::LeaseConfirmed (ui64 confirmedCookie) {
1650
+ bool leaseUpdated = false ;
1651
+ while (!LeaseCommits.empty ()) {
1652
+ auto & l = LeaseCommits.front ();
1653
+ if (l.Cookie <= confirmedCookie) {
1654
+ LeaseEnd = Max (LeaseEnd, l.LeaseEnd );
1655
+
1656
+ auto callbacks = std::move (l.Callbacks );
1657
+ LeaseCommitsByEnd.erase (l.ByEndIterator );
1658
+ LeaseCommits.pop_front ();
1659
+
1660
+ for (auto & callback : callbacks) {
1661
+ callback ();
1662
+ }
1663
+
1664
+ leaseUpdated = true ;
1665
+ } else {
1666
+ break ;
1667
+ }
1668
+ }
1669
+
1670
+ if (leaseUpdated && LeaseCommits.empty ()) {
1671
+ if (LeaseDurationIncreases < 2 ) {
1672
+ // Calculate how much of a lease is left after a full round trip
1673
+ // When we are left with less than a third of lease duration we want
1674
+ // to increase lease duration so we would have enough time for
1675
+ // processing read-only requests without additional commits
1676
+ TMonotonic ts = AppData ()->MonotonicTimeProvider ->Now ();
1677
+ if ((LeaseEnd - ts) < LeaseDuration / 3 ) {
1678
+ LeaseDuration *= 2 ;
1679
+ LeaseDurationUpdated = true ;
1680
+ ++LeaseDurationIncreases;
1681
+ }
1682
+ }
1683
+
1684
+ // We want to schedule a new commit before the lease expires
1685
+ if (!LeaseExtendPending) {
1686
+ Schedule (LeaseEnd - LeaseDuration / 3 , new TEvPrivate::TEvLeaseExtend);
1687
+ LeaseExtendPending = true ;
1688
+ }
1689
+ }
1690
+ }
1691
+
1692
+ TExecutor::TLeaseCommit* TExecutor::AddLeaseConfirm () {
1693
+ if (!LeaseEnabled || Y_UNLIKELY (LeaseDropped)) {
1694
+ return nullptr ;
1695
+ }
1696
+
1697
+ TMonotonic ts = AppData ()->MonotonicTimeProvider ->Now ();
1698
+ TLeaseCommit* lease = &LeaseCommits.emplace_back (0 , ts, ts + LeaseDuration, ++LeaseCommitsCounter);
1699
+ lease->ByEndIterator = LeaseCommitsByEnd.emplace (lease->LeaseEnd , lease);
1700
+
1701
+ Send (Owner->Tablet (), new TEvTablet::TEvConfirmLeader (Owner->TabletID (), Generation ()), 0 , lease->Cookie );
1702
+
1703
+ return lease;
1704
+ }
1705
+
1649
1706
TExecutor::TLeaseCommit* TExecutor::AttachLeaseCommit (TLogCommit* commit, bool force) {
1650
1707
if (!LeaseEnabled || Y_UNLIKELY (LeaseDropped)) {
1651
1708
return nullptr ;
@@ -1661,17 +1718,17 @@ TExecutor::TLeaseCommit* TExecutor::AttachLeaseCommit(TLogCommit* commit, bool f
1661
1718
Y_ENSURE (ok);
1662
1719
1663
1720
commit->Metadata .emplace_back (ui32 (NBoot::ELogCommitMeta::LeaseInfo), std::move (data));
1664
- LeaseDurationUpdated = false ;
1665
1721
}
1666
1722
1667
1723
TMonotonic ts = AppData ()->MonotonicTimeProvider ->Now ();
1668
- TLeaseCommit* lease = &LeaseCommits.emplace_back (commit->Step , ts, ts + LeaseDuration);
1724
+ TLeaseCommit* lease = &LeaseCommits.emplace_back (commit->Step , ts, ts + LeaseDuration, ++LeaseCommitsCounter);
1725
+ LeaseCommitsByStep.PushBack (lease);
1669
1726
1670
1727
// It may happen in the future that LeaseDuration is decreased by this
1671
1728
// commit, in which case new leader might read and use it, and may not wait
1672
1729
// longer than the new LeaseEnd. If there are commits currently in flight
1673
1730
// make sure to truncate their lease extensions to the new LeaseEnd.
1674
- if (force || LeaseDurationUpdated) {
1731
+ if (LeaseDurationUpdated) {
1675
1732
auto it = LeaseCommitsByEnd.upper_bound (lease->LeaseEnd );
1676
1733
while (it != LeaseCommitsByEnd.end ()) {
1677
1734
TLeaseCommit* other = it->second ;
@@ -1681,9 +1738,11 @@ TExecutor::TLeaseCommit* TExecutor::AttachLeaseCommit(TLogCommit* commit, bool f
1681
1738
}
1682
1739
// Currently confirmed lease may become truncated as well
1683
1740
LeaseEnd = Min (LeaseEnd, lease->LeaseEnd );
1741
+ LeaseDurationUpdated = false ;
1684
1742
}
1685
1743
1686
1744
lease->ByEndIterator = LeaseCommitsByEnd.emplace (lease->LeaseEnd , lease);
1745
+
1687
1746
return lease;
1688
1747
}
1689
1748
@@ -1707,16 +1766,22 @@ TExecutor::TLeaseCommit* TExecutor::EnsureReadOnlyLease(TMonotonic at) {
1707
1766
if (itAfter != LeaseCommitsByEnd.end ()) {
1708
1767
lease = itAfter->second ;
1709
1768
} else if (!LeaseDropped) {
1710
- LogicRedo->FlushBatchedLog ();
1769
+ if (LeaseDurationUpdated || !LeasePersisted) {
1770
+ // We need to make a real commit
1771
+ LogicRedo->FlushBatchedLog ();
1711
1772
1712
- auto commit = CommitManager->Begin (true , ECommit::Misc, {});
1773
+ auto commit = CommitManager->Begin (true , ECommit::Misc, {});
1713
1774
1714
- lease = AttachLeaseCommit (commit.Get (), /* force */ true );
1775
+ lease = AttachLeaseCommit (commit.Get (), /* force */ true );
1715
1776
1716
- CommitManager->Commit (commit);
1777
+ CommitManager->Commit (commit);
1717
1778
1718
- if (LogicSnap->MayFlush (false )) {
1719
- MakeLogSnapshot ();
1779
+ if (LogicSnap->MayFlush (false )) {
1780
+ MakeLogSnapshot ();
1781
+ }
1782
+ } else {
1783
+ // We want a lightweight confirmation
1784
+ lease = AddLeaseConfirm ();
1720
1785
}
1721
1786
}
1722
1787
@@ -3052,6 +3117,20 @@ void TExecutor::Handle(TEvPrivate::TEvLeaseExtend::TPtr &, const TActorContext &
3052
3117
EnsureReadOnlyLease (LeaseEnd);
3053
3118
}
3054
3119
3120
+ void TExecutor::Handle (TEvTablet::TEvConfirmLeaderResult::TPtr &ev) {
3121
+ auto *msg = ev->Get ();
3122
+
3123
+ // Note: lease confirmation error will currenly cause tablet to stop anyway
3124
+ if (msg->Status != NKikimrProto::OK) {
3125
+ if (auto logl = Logger->Log (ELnLev::Error)) {
3126
+ logl << NFmt::Do (*this ) << " Broken on lease confirmation" ;
3127
+ }
3128
+ return Broken ();
3129
+ }
3130
+
3131
+ LeaseConfirmed (ev->Cookie );
3132
+ }
3133
+
3055
3134
void TExecutor::Handle (TEvTablet::TEvCommitResult::TPtr &ev, const TActorContext &ctx) {
3056
3135
TEvTablet::TEvCommitResult *msg = ev->Get ();
3057
3136
@@ -3078,39 +3157,12 @@ void TExecutor::Handle(TEvTablet::TEvCommitResult::TPtr &ev, const TActorContext
3078
3157
<< " for step " << step;
3079
3158
}
3080
3159
3081
- if (!LeaseCommits. empty ()) {
3082
- auto & l = LeaseCommits. front ();
3083
- Y_ENSURE (step <= l. Step );
3084
- if (step == l. Step ) {
3160
+ if (!LeaseCommitsByStep. Empty ()) {
3161
+ auto * l = LeaseCommitsByStep. Front ();
3162
+ Y_ENSURE (step <= l-> Step );
3163
+ if (step == l-> Step ) {
3085
3164
LeasePersisted = true ;
3086
- LeaseEnd = Max (LeaseEnd, l.LeaseEnd );
3087
-
3088
- auto callbacks = std::move (l.Callbacks );
3089
- LeaseCommitsByEnd.erase (l.ByEndIterator );
3090
- LeaseCommits.pop_front ();
3091
-
3092
- for (auto & callback : callbacks) {
3093
- callback ();
3094
- }
3095
-
3096
- if (LeaseDurationIncreases < 2 && LeaseCommits.empty ()) {
3097
- // Calculate how much of a lease is left after a full round trip
3098
- // When we are left with less than a third of lease duration we want
3099
- // to increase lease duration so we would have enough time for
3100
- // processing read-only requests without additional commits
3101
- TMonotonic ts = AppData ()->MonotonicTimeProvider ->Now ();
3102
- if ((LeaseEnd - ts) < LeaseDuration / 3 ) {
3103
- LeaseDuration *= 2 ;
3104
- LeaseDurationUpdated = true ;
3105
- ++LeaseDurationIncreases;
3106
- }
3107
- }
3108
-
3109
- // We want to schedule a new commit before the lease expires
3110
- if (LeaseCommits.empty () && !LeaseExtendPending) {
3111
- Schedule (LeaseEnd - LeaseDuration / 3 , new TEvPrivate::TEvLeaseExtend);
3112
- LeaseExtendPending = true ;
3113
- }
3165
+ LeaseConfirmed (l->Cookie );
3114
3166
}
3115
3167
}
3116
3168
@@ -4154,6 +4206,7 @@ STFUNC(TExecutor::StateWork) {
4154
4206
hFunc (NSharedCache::TEvUpdated, Handle);
4155
4207
HFunc (TEvTablet::TEvDropLease, Handle);
4156
4208
HFunc (TEvTablet::TEvCommitResult, Handle);
4209
+ hFunc (TEvTablet::TEvConfirmLeaderResult, Handle);
4157
4210
hFunc (TEvTablet::TEvCheckBlobstorageStatusResult, Handle);
4158
4211
hFunc (TEvBlobStorage::TEvCollectGarbageResult, Handle);
4159
4212
HFunc (TEvBlobStorage::TEvGetResult, Handle);
0 commit comments