//true if at least one entry from current term is stored on this node; otherwise, false private static async Task <Result <bool> > AppendEntriesAsync(IRaftClusterMember member, long commitIndex, long term, IAuditTrail <ILogEntry> transactionLog, ILogger logger, CancellationToken token) { var currentIndex = transactionLog.GetLastIndex(false); logger.ReplicationStarted(member.Endpoint, currentIndex); var precedingIndex = Math.Max(0, member.NextIndex - 1); var precedingTerm = (await transactionLog.GetEntryAsync(precedingIndex).ConfigureAwait(false) ?? transactionLog.First).Term; var entries = currentIndex >= member.NextIndex ? await transactionLog.GetEntriesAsync(member.NextIndex).ConfigureAwait(false) : Array.Empty <ILogEntry>(); logger.ReplicaSize(member.Endpoint, entries.Count, precedingIndex, precedingTerm); //trying to replicate var result = await member .AppendEntriesAsync(term, entries, precedingIndex, precedingTerm, commitIndex, token) .ConfigureAwait(false); if (result.Value) { logger.ReplicationSuccessful(member.Endpoint, member.NextIndex); member.NextIndex.VolatileWrite(currentIndex + 1); //checks whether the at least one entry from current term is stored on this node result = result.SetValue(entries.Any(entry => entry.Term == term)); } else { logger.ReplicationFailed(member.Endpoint, member.NextIndex.DecrementAndGet()); } return(result); }
internal static async ValueTask <LogEntry> GetEntryAsync <LogEntry>(this IAuditTrail <LogEntry> auditTrail, long index) where LogEntry : class, IMessage { var entries = await auditTrail.GetEntriesAsync(index, index).ConfigureAwait(false); return(entries.Count > 0 ? entries[0] : null); }
private static async void OnCommitted(IAuditTrail <ILogEntry> sender, long startIndex, long count) { foreach (var entry in await sender.GetEntriesAsync(startIndex, startIndex + count).ConfigureAwait(false)) { var content = await entry.ReadAsTextAsync().ConfigureAwait(false); Console.WriteLine($"Message '{content}' is committed at term {entry.Term}"); } }