Skip to content

Commit e8ad60a

Browse files
authored
Fix a regression in IHostedService startup order (#181)
1 parent 91c6d2b commit e8ad60a

File tree

5 files changed

+44
-6
lines changed

5 files changed

+44
-6
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ az-login-from-host:
3838
scripts/az-login-from-host.sh
3939

4040
build-csharp:
41-
find . -name *csproj | xargs -L 1 dotnet build
41+
dotnet build server/tyger.sln
4242

4343
build-go:
4444
cd cli
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
namespace Tyger.Common.DependencyInjection;
5+
6+
public static class ServiceOrderHostApplicationBuilderExtensions
7+
{
8+
/// <summary>
9+
/// Adds a service descriptor to the IHostApplicationBuilder with a specified priority.
10+
/// </summary>
11+
/// <remarks>
12+
/// If a service descriptor with the same service type already exists, the new service descriptor
13+
/// will be inserted before the existing one if the new service's priority is higher. Otherwise, it will be added
14+
/// to the end of the service collection. Services added outside of this method have priority 0.
15+
/// </remarks>
16+
public static IHostApplicationBuilder AddServiceWithPriority(this IHostApplicationBuilder builder, ServiceDescriptor serviceDescriptor, int priority)
17+
{
18+
builder.Properties[serviceDescriptor] = priority;
19+
for (int i = 0; i < builder.Services.Count; i++)
20+
{
21+
var existingService = builder.Services[i];
22+
if (existingService.ServiceType == serviceDescriptor.ServiceType)
23+
{
24+
var existingPriority = builder.Properties.TryGetValue(existingService, out var value) ? (int)value : 0;
25+
if (priority > existingPriority)
26+
{
27+
builder.Services.Insert(i, serviceDescriptor);
28+
return builder;
29+
}
30+
}
31+
}
32+
33+
builder.Services.Add(serviceDescriptor);
34+
return builder;
35+
}
36+
}

server/ControlPlane/Buffers/Buffers.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.Extensions.Primitives;
88
using Microsoft.OpenApi.Models;
99
using Tyger.Common.Api;
10+
using Tyger.Common.DependencyInjection;
1011
using Tyger.ControlPlane.Json;
1112
using Tyger.ControlPlane.Model;
1213
using Buffer = Tyger.ControlPlane.Model.Buffer;
@@ -35,7 +36,7 @@ public static void AddBuffers(this IHostApplicationBuilder builder)
3536
{
3637
builder.Services.AddSingleton<AzureBlobBufferProvider>();
3738
builder.Services.AddSingleton<IBufferProvider>(sp => sp.GetRequiredService<AzureBlobBufferProvider>());
38-
builder.Services.Insert(0, ServiceDescriptor.Singleton<IHostedService>(sp => sp.GetRequiredService<AzureBlobBufferProvider>())); // Other startup services depend on this, so we add it early.
39+
builder.AddServiceWithPriority(ServiceDescriptor.Singleton<IHostedService>(sp => sp.GetRequiredService<AzureBlobBufferProvider>()), 10);
3940
builder.Services.AddHealthChecks().AddCheck<AzureBlobBufferProvider>("buffers");
4041
}
4142

server/ControlPlane/Compute/Kubernetes/Kubernetes.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Microsoft.Extensions.Http.Resilience;
99
using Microsoft.Extensions.Options;
1010
using Polly;
11+
using Tyger.Common.DependencyInjection;
1112
using Tyger.ControlPlane.Buffers;
1213
using Tyger.ControlPlane.Database;
1314
using Tyger.ControlPlane.Logging;
@@ -51,8 +52,7 @@ public static void AddKubernetes(this IHostApplicationBuilder builder)
5152
builder.Services.AddOptions<KubernetesApiOptions>().BindConfiguration("compute:kubernetes").ValidateDataAnnotations().ValidateOnStart();
5253

5354
builder.Services.AddSingleton(sp => new LeaseManager(sp.GetRequiredService<Repository>(), "tyger-server-leader"));
54-
builder.Services.Insert(0, ServiceDescriptor.Singleton<IHostedService>(sp => sp.GetRequiredService<LeaseManager>())); // Other startup services depend on this, so we add it early.
55-
55+
builder.AddServiceWithPriority(ServiceDescriptor.Singleton<IHostedService>(sp => sp.GetRequiredService<LeaseManager>()), 20);
5656
builder.Services.AddSingleton<KubernetesRunCreator>();
5757
builder.Services.AddSingleton<IRunCreator>(sp => sp.GetRequiredService<KubernetesRunCreator>());
5858
builder.Services.AddHostedService(sp => sp.GetRequiredService<KubernetesRunCreator>());

server/ControlPlane/Database/Database.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Npgsql;
1212
using Polly;
1313
using Polly.Retry;
14+
using Tyger.Common.DependencyInjection;
1415
using Tyger.ControlPlane.Compute.Kubernetes;
1516
using Tyger.ControlPlane.Database.Migrations;
1617
using Tyger.ControlPlane.Model;
@@ -105,10 +106,10 @@ public static void AddDatabase(this IHostApplicationBuilder builder)
105106
});
106107

107108
builder.Services.AddSingleton<MigrationRunner>();
108-
builder.Services.AddHostedService(sp => sp.GetRequiredService<MigrationRunner>());
109+
builder.AddServiceWithPriority(ServiceDescriptor.Singleton<IHostedService>(sp => sp.GetRequiredService<MigrationRunner>()), 200);
109110

110111
builder.Services.AddSingleton<DatabaseVersions>();
111-
builder.Services.AddHostedService(sp => sp.GetRequiredService<DatabaseVersions>());
112+
builder.AddServiceWithPriority(ServiceDescriptor.Singleton<IHostedService>(sp => sp.GetRequiredService<DatabaseVersions>()), 100);
112113
builder.Services.AddHealthChecks().AddCheck<DatabaseVersions>("database");
113114
}
114115

0 commit comments

Comments
 (0)