Skip to content

Commit 46a2bd2

Browse files
committed
fix(surrealdb): improve surrealdb healthchecks
1 parent 0c0afa1 commit 46a2bd2

File tree

4 files changed

+73
-49
lines changed

4 files changed

+73
-49
lines changed

src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbBuilderExtensions.cs

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,10 @@ public static IResourceBuilder<SurrealDbServerResource> AddSurrealServer(
8181
: SurrealDbContainerImageTags.Tag;
8282

8383
var surrealServer = new SurrealDbServerResource(name, userName?.Resource, passwordParameter);
84-
84+
8585
return builder.AddResource(surrealServer)
8686
.WithEndpoint(port: port, targetPort: SurrealDbPort, name: SurrealDbServerResource.PrimaryEndpointName)
87+
.WithHttpEndpoint(port: port, targetPort: SurrealDbPort, name: SurrealDbServerResource.SecondaryEndpointName)
8788
.WithImage(SurrealDbContainerImageTags.Image, imageTag)
8889
.WithImageRegistry(SurrealDbContainerImageTags.Registry)
8990
.WithEnvironment(context =>
@@ -93,6 +94,7 @@ public static IResourceBuilder<SurrealDbServerResource> AddSurrealServer(
9394
})
9495
.WithEntrypoint("/surreal")
9596
.WithArgs([.. args])
97+
.WithHttpHealthCheck("/health")
9698
.OnResourceReady(async (_, @event, ct) =>
9799
{
98100
if (!strictMode)
@@ -106,33 +108,44 @@ public static IResourceBuilder<SurrealDbServerResource> AddSurrealServer(
106108
throw new DistributedApplicationException($"ResourceReadyEvent was published for the '{surrealServer.Name}' resource but the connection string was null.");
107109
}
108110

109-
var options = new SurrealDbOptionsBuilder().FromConnectionString(connectionString).Build();
110-
await using var surrealClient = new SurrealDbClient(options);
111+
await EnsuresNsDbCreated(builder, connectionString, surrealServer, @event.Services, ct);
112+
});
113+
}
114+
115+
private static async Task EnsuresNsDbCreated(
116+
IDistributedApplicationBuilder builder,
117+
string connectionString,
118+
SurrealDbServerResource surrealServer,
119+
IServiceProvider services,
120+
CancellationToken ct
121+
)
122+
{
123+
var options = new SurrealDbOptionsBuilder().FromConnectionString(connectionString).Build();
124+
await using var surrealClient = new SurrealDbClient(options);
111125

112-
foreach (var nsResourceName in surrealServer.Namespaces.Keys)
113-
{
114-
if (builder.Resources.FirstOrDefault(n =>
115-
string.Equals(n.Name, nsResourceName, StringComparison.OrdinalIgnoreCase)) is
116-
SurrealDbNamespaceResource surrealDbNamespace)
117-
{
118-
await CreateNamespaceAsync(surrealClient, surrealDbNamespace, @event.Services, ct)
119-
.ConfigureAwait(false);
126+
foreach (var nsResourceName in surrealServer.Namespaces.Keys)
127+
{
128+
if (builder.Resources.FirstOrDefault(n =>
129+
string.Equals(n.Name, nsResourceName, StringComparison.OrdinalIgnoreCase)) is
130+
SurrealDbNamespaceResource surrealDbNamespace)
131+
{
132+
await CreateNamespaceAsync(surrealClient, surrealDbNamespace, services, ct)
133+
.ConfigureAwait(false);
120134

121-
await surrealClient.Use(surrealDbNamespace.NamespaceName, null!, ct).ConfigureAwait(false);
135+
await surrealClient.Use(surrealDbNamespace.NamespaceName, null!, ct).ConfigureAwait(false);
122136

123-
foreach (var dbResourceName in surrealDbNamespace.Databases.Keys)
124-
{
125-
if (builder.Resources.FirstOrDefault(n =>
126-
string.Equals(n.Name, dbResourceName, StringComparison.OrdinalIgnoreCase)) is
127-
SurrealDbDatabaseResource surrealDbDatabase)
128-
{
129-
await CreateDatabaseAsync(surrealClient, surrealDbDatabase, @event.Services, ct)
130-
.ConfigureAwait(false);
131-
}
132-
}
133-
}
134-
}
135-
});
137+
foreach (var dbResourceName in surrealDbNamespace.Databases.Keys)
138+
{
139+
if (builder.Resources.FirstOrDefault(n =>
140+
string.Equals(n.Name, dbResourceName, StringComparison.OrdinalIgnoreCase)) is
141+
SurrealDbDatabaseResource surrealDbDatabase)
142+
{
143+
await CreateDatabaseAsync(surrealClient, surrealDbDatabase, services, ct)
144+
.ConfigureAwait(false);
145+
}
146+
}
147+
}
148+
}
136149
}
137150

138151
/// <summary>
@@ -234,24 +247,10 @@ public static IResourceBuilder<SurrealDbDatabaseResource> AddDatabase(
234247

235248
SurrealDbClient? surrealDbClient = null;
236249

237-
builder.ApplicationBuilder.Eventing.Subscribe<ConnectionStringAvailableEvent>(surrealServerDatabase, async (@event, ct) =>
238-
{
239-
var connectionString = await surrealServerDatabase.ConnectionStringExpression.GetValueAsync(ct).ConfigureAwait(false);
240-
if (connectionString is null)
241-
{
242-
throw new DistributedApplicationException($"ConnectionStringAvailableEvent was published for the '{surrealServerDatabase}' resource but the connection string was null.");
243-
}
244-
245-
var options = new SurrealDbOptionsBuilder().FromConnectionString(connectionString).Build();
246-
surrealDbClient = new SurrealDbClient(options);
247-
});
248-
249250
string namespaceName = builder.Resource.Name;
250251
string serverName = builder.Resource.Parent.Name;
251252

252253
string healthCheckKey = $"{serverName}_{namespaceName}_{name}_check";
253-
// TODO : Bug to be fixed
254-
//builder.ApplicationBuilder.Services.AddHealthChecks().AddSurreal(_ => surrealDbClient!, healthCheckKey);
255254
builder.ApplicationBuilder.Services.AddHealthChecks().Add(new HealthCheckRegistration(
256255
name: healthCheckKey,
257256
_ => new SurrealDbHealthCheck(surrealDbClient!),
@@ -261,7 +260,17 @@ public static IResourceBuilder<SurrealDbDatabaseResource> AddDatabase(
261260
);
262261

263262
return builder.ApplicationBuilder.AddResource(surrealServerDatabase)
264-
.WithHealthCheck(healthCheckKey);
263+
.WithHealthCheck(healthCheckKey)
264+
.OnConnectionStringAvailable(async (_, _, ct) => {
265+
var connectionString = await surrealServerDatabase.ConnectionStringExpression.GetValueAsync(ct).ConfigureAwait(false);
266+
if (connectionString is null)
267+
{
268+
throw new DistributedApplicationException($"ConnectionStringAvailableEvent was published for the '{surrealServerDatabase}' resource but the connection string was null.");
269+
}
270+
271+
var options = new SurrealDbOptionsBuilder().FromConnectionString(connectionString).Build();
272+
surrealDbClient = new SurrealDbClient(options);
273+
});
265274
}
266275

267276
/// <summary>

src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbServerResource.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace Aspire.Hosting.ApplicationModel;
99
public class SurrealDbServerResource : ContainerResource, IResourceWithConnectionString
1010
{
1111
internal const string PrimaryEndpointName = "tcp";
12+
internal const string SecondaryEndpointName = "http";
1213

1314
private const string DefaultUserName = "root";
1415
private const string SchemeUri = "ws";

src/CommunityToolkit.Aspire.SurrealDb/SurrealDbHealthCheck.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context
2222
try
2323
{
2424
bool isHealthy = await _surrealdbClient.Health(cancellationToken).ConfigureAwait(false);
25-
25+
var response = await _surrealdbClient.RawQuery("RETURN 1", cancellationToken: cancellationToken).ConfigureAwait(false);
26+
response.EnsureAllOks();
27+
2628
return isHealthy
2729
? HealthCheckResult.Healthy()
2830
: new HealthCheckResult(context.Registration.FailureStatus);

tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/AddSurrealServerTests.cs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,26 @@ public async Task AddSurrealServerContainerWithDefaultsAddsAnnotationMetadata()
4343
var containerResource = Assert.Single(appModel.Resources.OfType<SurrealDbServerResource>());
4444
Assert.Equal("surreal", containerResource.Name);
4545

46-
var endpoint = Assert.Single(containerResource.Annotations.OfType<EndpointAnnotation>());
47-
Assert.Equal(8000, endpoint.TargetPort);
48-
Assert.False(endpoint.IsExternal);
49-
Assert.Equal("tcp", endpoint.Name);
50-
Assert.Null(endpoint.Port);
51-
Assert.Equal(ProtocolType.Tcp, endpoint.Protocol);
52-
Assert.Equal("tcp", endpoint.Transport);
53-
Assert.Equal("tcp", endpoint.UriScheme);
46+
var endpoints = containerResource.Annotations.OfType<EndpointAnnotation>().ToList();
47+
Assert.Equal(2, endpoints.Count);
48+
49+
var tcpEndpoint = endpoints.First(e => e.Name == "tcp");
50+
Assert.Equal(8000, tcpEndpoint.TargetPort);
51+
Assert.False(tcpEndpoint.IsExternal);
52+
Assert.Equal("tcp", tcpEndpoint.Name);
53+
Assert.Null(tcpEndpoint.Port);
54+
Assert.Equal(ProtocolType.Tcp, tcpEndpoint.Protocol);
55+
Assert.Equal("tcp", tcpEndpoint.Transport);
56+
Assert.Equal("tcp", tcpEndpoint.UriScheme);
57+
58+
var httpEndpoint = endpoints.First(e => e.Name == "http");
59+
Assert.Equal(8000, httpEndpoint.TargetPort);
60+
Assert.False(httpEndpoint.IsExternal);
61+
Assert.Equal("http", httpEndpoint.Name);
62+
Assert.Null(httpEndpoint.Port);
63+
Assert.Equal(ProtocolType.Tcp, httpEndpoint.Protocol);
64+
Assert.Equal("http", httpEndpoint.Transport);
65+
Assert.Equal("http", httpEndpoint.UriScheme);
5466

5567
var containerAnnotation = Assert.Single(containerResource.Annotations.OfType<ContainerImageAnnotation>());
5668
Assert.Equal(SurrealDbContainerImageTags.Tag + "-dev", containerAnnotation.Tag);

0 commit comments

Comments
 (0)