public void Apply(TransactionOperationContext context, long uptoInclusive, Leader leader, ServerStore serverStore) { Debug.Assert(context.Transaction != null); var lastAppliedIndex = _parent.GetLastCommitIndex(context); for (var index = lastAppliedIndex + 1; index <= uptoInclusive; index++) { var cmd = _parent.GetEntry(context, index, out RachisEntryFlags flags); if (cmd == null || flags == RachisEntryFlags.Invalid) { throw new InvalidOperationException("Expected to apply entry " + index + " but it isn't stored"); } if (flags != RachisEntryFlags.StateMachineCommand) { continue; } Apply(context, cmd, index, leader, serverStore); } var term = _parent.GetTermForKnownExisting(context, uptoInclusive); _parent.SetLastCommitIndex(context, uptoInclusive, term); }
public long Apply(ClusterOperationContext context, long uptoInclusive, Leader leader, ServerStore serverStore, Stopwatch duration) { Debug.Assert(context.Transaction != null); var lastAppliedIndex = _parent.GetLastCommitIndex(context); var maxTimeAllowedToWaitForApply = _parent.Timeout.TimeoutPeriod / 4; for (var index = lastAppliedIndex + 1; index <= uptoInclusive; index++) { var cmd = _parent.GetEntry(context, index, out RachisEntryFlags flags); if (cmd == null || flags == RachisEntryFlags.Invalid) { throw new InvalidOperationException("Expected to apply entry " + index + " but it isn't stored"); } lastAppliedIndex = index; if (flags != RachisEntryFlags.StateMachineCommand) { _parent.LogHistory.UpdateHistoryLog(context, index, _parent.CurrentTerm, cmd, null, null); var currentIndex = index; context.Transaction.InnerTransaction.LowLevelTransaction.OnDispose += t => { if (t is LowLevelTransaction llt && llt.Committed) { serverStore.Cluster.NotifyAndSetCompleted(currentIndex); } }; continue; } Apply(context, cmd, index, leader, serverStore); if (duration.ElapsedMilliseconds >= maxTimeAllowedToWaitForApply) { // we don't want to spend so much time applying commands that we will time out the leader // so we time this from the follower perspective and abort after applying a single command // or 25% of the time has already passed break; } } var term = _parent.GetTermForKnownExisting(context, lastAppliedIndex); _parent.SetLastCommitIndex(context, lastAppliedIndex, term); return(lastAppliedIndex); }