Skip to content

Commit 0cb782e

Browse files
committed
Migrate RaftNode example to AOT
1 parent d56aff9 commit 0cb782e

File tree

3 files changed

+75
-89
lines changed

3 files changed

+75
-89
lines changed

src/examples/RaftNode/Program.cs

Lines changed: 73 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using System.Net;
22
using System.Reflection;
33
using System.Security.Cryptography.X509Certificates;
4+
using DotNext;
45
using DotNext.Net.Cluster.Consensus.Raft;
56
using DotNext.Net.Cluster.Consensus.Raft.Http;
67
using DotNext.Net.Cluster.Consensus.Raft.Membership;
8+
using Microsoft.AspNetCore.Connections;
79
using RaftNode;
10+
using static System.Globalization.CultureInfo;
811
using SslOptions = DotNext.Net.Security.SslOptions;
912

1013
switch (args.LongLength)
@@ -21,34 +24,80 @@
2124
break;
2225
}
2326

24-
static Task UseAspNetCoreHost(int port, string? persistentStorage = null)
27+
static async Task UseAspNetCoreHost(int port, string? persistentStorage = null)
2528
{
2629
var configuration = new Dictionary<string, string?>
27-
{
28-
{"partitioning", "false"},
29-
{"lowerElectionTimeout", "150" },
30-
{"upperElectionTimeout", "300" },
31-
{"requestTimeout", "00:10:00"},
32-
{"publicEndPoint", $"https://localhost:{port}"},
33-
{"coldStart", "false"},
34-
{"requestJournal:memoryLimit", "5" },
35-
{"requestJournal:expiration", "00:01:00" }
36-
};
37-
if (!string.IsNullOrEmpty(persistentStorage))
38-
configuration[SimplePersistentState.LogLocation] = persistentStorage;
39-
return new HostBuilder().ConfigureWebHost(webHost =>
4030
{
41-
webHost.UseKestrel(options =>
31+
{ "partitioning", "false" },
32+
{ "lowerElectionTimeout", "150" },
33+
{ "upperElectionTimeout", "300" },
34+
{ "requestTimeout", "00:10:00" },
35+
{ "publicEndPoint", $"https://localhost:{port}" },
36+
{ "coldStart", "false" },
37+
{ "requestJournal:memoryLimit", "5" },
38+
{ "requestJournal:expiration", "00:01:00" },
39+
{ SimplePersistentState.LogLocation, persistentStorage },
40+
};
41+
42+
var builder = WebApplication.CreateSlimBuilder();
43+
builder.Configuration.AddInMemoryCollection(configuration);
44+
builder.WebHost.ConfigureKestrel(options =>
45+
{
46+
options.ListenLocalhost(port, static listener => listener.UseHttps(LoadCertificate()));
47+
});
48+
49+
builder.Services
50+
.UseInMemoryConfigurationStorage(AddClusterMembers)
51+
.ConfigureCluster<ClusterConfigurator>()
52+
.AddSingleton<IHttpMessageHandlerFactory, RaftClientHandlerFactory>()
53+
.AddOptions()
54+
.AddRouting();
55+
56+
if (!string.IsNullOrWhiteSpace(persistentStorage))
57+
{
58+
builder.Services.UsePersistenceEngine<ISupplier<long>, SimplePersistentState>()
59+
.AddSingleton<IHostedService, DataModifier>();
60+
}
61+
62+
ConfigureLogging(builder.Logging);
63+
builder.JoinCluster();
64+
65+
await using var app = builder.Build();
66+
67+
const string leaderResource = "/leader";
68+
const string valueResource = "/value";
69+
app.UseConsensusProtocolHandler()
70+
.RedirectToLeader(leaderResource)
71+
.UseRouting()
72+
.UseEndpoints(static endpoints =>
4273
{
43-
options.ListenLocalhost(port, static listener => listener.UseHttps(LoadCertificate()));
44-
})
45-
.UseStartup<Startup>();
46-
})
47-
.ConfigureLogging(ConfigureLogging)
48-
.ConfigureAppConfiguration(builder => builder.AddInMemoryCollection(configuration))
49-
.JoinCluster()
50-
.Build()
51-
.RunAsync();
74+
endpoints.MapGet(leaderResource, RedirectToLeaderAsync);
75+
endpoints.MapGet(valueResource, GetValueAsync);
76+
});
77+
await app.RunAsync();
78+
79+
static Task RedirectToLeaderAsync(HttpContext context)
80+
{
81+
var cluster = context.RequestServices.GetRequiredService<IRaftCluster>();
82+
return context.Response.WriteAsync($"Leader address is {cluster.Leader?.EndPoint}. Current address is {context.Connection.LocalIpAddress}:{context.Connection.LocalPort}", context.RequestAborted);
83+
}
84+
85+
static async Task GetValueAsync(HttpContext context)
86+
{
87+
var cluster = context.RequestServices.GetRequiredService<IRaftCluster>();
88+
var provider = context.RequestServices.GetRequiredService<ISupplier<long>>();
89+
90+
await cluster.ApplyReadBarrierAsync(context.RequestAborted);
91+
await context.Response.WriteAsync(provider.Invoke().ToString(InvariantCulture), context.RequestAborted);
92+
}
93+
94+
// NOTE: this way of adding members to the cluster is not recommended in production code
95+
static void AddClusterMembers(ICollection<UriEndPoint> members)
96+
{
97+
members.Add(new UriEndPoint(new("https://localhost:3262", UriKind.Absolute)));
98+
members.Add(new UriEndPoint(new("https://localhost:3263", UriKind.Absolute)));
99+
members.Add(new UriEndPoint(new("https://localhost:3264", UriKind.Absolute)));
100+
}
52101
}
53102

54103
static async Task UseConfiguration(RaftCluster.NodeConfiguration config, string? persistentStorage)

src/examples/RaftNode/RaftNode.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
<LangVersion>latest</LangVersion>
77
<Nullable>enable</Nullable>
88
<ImplicitUsings>true</ImplicitUsings>
9-
<Version>5.11.0</Version>
9+
<Version>5.17.0</Version>
10+
<PublishAot>true</PublishAot>
1011
</PropertyGroup>
1112

1213
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Bench|AnyCPU'">

src/examples/RaftNode/Startup.cs

Lines changed: 0 additions & 64 deletions
This file was deleted.

0 commit comments

Comments
 (0)