63 lines
1.8 KiB
C#
63 lines
1.8 KiB
C#
namespace NATS.Server.Raft;
|
|
|
|
public sealed class RaftLog
|
|
{
|
|
private readonly List<RaftLogEntry> _entries = [];
|
|
private long _baseIndex;
|
|
|
|
public IReadOnlyList<RaftLogEntry> Entries => _entries;
|
|
|
|
public RaftLogEntry Append(int term, string command)
|
|
{
|
|
var entry = new RaftLogEntry(_baseIndex + _entries.Count + 1, term, command);
|
|
_entries.Add(entry);
|
|
return entry;
|
|
}
|
|
|
|
public void AppendReplicated(RaftLogEntry entry)
|
|
{
|
|
if (_entries.Any(e => e.Index == entry.Index))
|
|
return;
|
|
|
|
_entries.Add(entry);
|
|
}
|
|
|
|
public void ReplaceWithSnapshot(RaftSnapshot snapshot)
|
|
{
|
|
_entries.Clear();
|
|
_baseIndex = snapshot.LastIncludedIndex;
|
|
}
|
|
|
|
public async Task PersistAsync(string path, CancellationToken ct)
|
|
{
|
|
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
|
|
var model = new PersistedLog
|
|
{
|
|
BaseIndex = _baseIndex,
|
|
Entries = [.. _entries],
|
|
};
|
|
await File.WriteAllTextAsync(path, System.Text.Json.JsonSerializer.Serialize(model), ct);
|
|
}
|
|
|
|
public static async Task<RaftLog> LoadAsync(string path, CancellationToken ct)
|
|
{
|
|
var log = new RaftLog();
|
|
if (!File.Exists(path))
|
|
return log;
|
|
|
|
var json = await File.ReadAllTextAsync(path, ct);
|
|
var model = System.Text.Json.JsonSerializer.Deserialize<PersistedLog>(json) ?? new PersistedLog();
|
|
log._baseIndex = model.BaseIndex;
|
|
log._entries.AddRange(model.Entries);
|
|
return log;
|
|
}
|
|
|
|
private sealed class PersistedLog
|
|
{
|
|
public long BaseIndex { get; set; }
|
|
public List<RaftLogEntry> Entries { get; set; } = [];
|
|
}
|
|
}
|
|
|
|
public sealed record RaftLogEntry(long Index, int Term, string Command);
|