Skip to content
This repository was archived by the owner on Sep 3, 2024. It is now read-only.

Commit 1650906

Browse files
split out readyness and live checks
1 parent ddd281a commit 1650906

File tree

3 files changed

+71
-8
lines changed

3 files changed

+71
-8
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System.Threading.Tasks;
2+
using Microsoft.AspNetCore.Builder;
3+
using Microsoft.AspNetCore.Routing;
4+
using MidFunc = System.Func<
5+
Microsoft.AspNetCore.Http.HttpContext,
6+
System.Func<System.Threading.Tasks.Task>,
7+
System.Threading.Tasks.Task
8+
>;
9+
10+
namespace SqlStreamStore.Server
11+
{
12+
internal static class HealthProbeMiddleware
13+
{
14+
public static IApplicationBuilder UseHealthProbe(
15+
this IApplicationBuilder builder, IReadonlyStreamStore streamStore)
16+
=> builder.UseRouter(router => router
17+
.MapMiddlewareGet("ready", inner => inner.Use(Ready(streamStore)))
18+
.MapMiddlewareGet("live", inner => inner.Use(Live)));
19+
20+
private static MidFunc Live => (context, next) =>
21+
{
22+
context.Response.StatusCode = 204;
23+
return Task.CompletedTask;
24+
};
25+
26+
private static MidFunc Ready(IReadonlyStreamStore streamStore) => async (context, next) =>
27+
{
28+
try
29+
{
30+
await streamStore.ReadHeadPosition(context.RequestAborted);
31+
}
32+
catch
33+
{
34+
context.Response.StatusCode = 503;
35+
return;
36+
}
37+
38+
context.Response.StatusCode = 204;
39+
};
40+
}
41+
}

src/SqlStreamStore.Server/SqlStreamStoreServerStartup.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@
66
using Microsoft.Extensions.DependencyInjection;
77
using SqlStreamStore.HAL;
88
using SqlStreamStore.Server.Browser;
9+
using MidFunc = System.Func<
10+
Microsoft.AspNetCore.Http.HttpContext,
11+
System.Func<System.Threading.Tasks.Task>,
12+
System.Threading.Tasks.Task
13+
>;
914

1015
namespace SqlStreamStore.Server
1116
{
12-
using MidFunc = System.Func<
13-
Microsoft.AspNetCore.Http.HttpContext,
14-
System.Func<System.Threading.Tasks.Task>,
15-
System.Threading.Tasks.Task
16-
>;
17-
1817
internal class SqlStreamStoreServerStartup : IStartup
1918
{
2019
private readonly IStreamStore _streamStore;
@@ -29,11 +28,12 @@ public SqlStreamStoreServerStartup(
2928
}
3029

3130
public IServiceProvider ConfigureServices(IServiceCollection services) => services
32-
.AddResponseCompression(options => options.MimeTypes = new[] { "application/hal+json" })
31+
.AddResponseCompression(options => options.MimeTypes = new[] {"application/hal+json"})
3332
.AddRouting()
3433
.BuildServiceProvider();
3534

3635
public void Configure(IApplicationBuilder app) => app
36+
.Map("/health", inner => inner.UseHealthProbe(_streamStore))
3737
.UseResponseCompression()
3838
.Use(VaryAccept)
3939
.UseSqlStreamStoreBrowser()

tests/SqlStreamStore.Server.Tests/SqlStreamStoreServerStartupTests.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Net;
23
using System.Net.Http;
34
using System.Net.Http.Headers;
45
using System.Threading.Tasks;
@@ -39,14 +40,35 @@ public SqlStreamStoreServerStartupTests()
3940
[Fact]
4041
public async Task StartsUp()
4142
{
42-
using (await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/")
43+
using (var response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/")
4344
{
4445
Headers = {Accept = {new MediaTypeWithQualityHeaderValue("application/hal+json")}}
4546
}))
4647
{
48+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
49+
}
50+
51+
using (var response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/health/ready")))
52+
{
53+
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
54+
}
55+
56+
using (var response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/health/live")))
57+
{
58+
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
4759
}
4860
}
4961

62+
[Fact]
63+
public async Task ServiceUnavailableWhenNotReady()
64+
{
65+
_streamStore.Dispose();
66+
using (var response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/health/ready")))
67+
{
68+
Assert.Equal(HttpStatusCode.ServiceUnavailable, response.StatusCode);
69+
}
70+
}
71+
5072
public void Dispose()
5173
{
5274
_streamStore?.Dispose();

0 commit comments

Comments
 (0)