Skip to content

Commit 76a85fd

Browse files
Allow for conditional warmup tasks based on IOptions (#9086)
1 parent 5d9ec73 commit 76a85fd

15 files changed

+749
-203
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
using HotChocolate.Execution.Configuration;
3+
using HotChocolate.Adapters.OpenApi;
4+
using Microsoft.Extensions.DependencyInjection.Extensions;
5+
6+
// ReSharper disable once CheckNamespace
7+
namespace Microsoft.Extensions.DependencyInjection;
8+
9+
public static class OpenApiRequestExecutorBuilderExtensions
10+
{
11+
/// <summary>
12+
/// Adds an OpenAPI definition storage to the gateway.
13+
/// </summary>
14+
/// <param name="builder">
15+
/// The <see cref="IRequestExecutorBuilder"/>.
16+
/// </param>
17+
/// <param name="storage">
18+
/// The OpenAPI definition storage instance.
19+
/// </param>
20+
/// <param name="skipIf">
21+
/// A function that is called to determine if the storage should be registered or not.
22+
/// If <c>true</c> is returned, the storage will not be registered.
23+
/// </param>
24+
/// <returns>
25+
/// Returns the <see cref="IRequestExecutorBuilder"/> so that configuration can be chained.
26+
/// </returns>
27+
/// <exception cref="ArgumentNullException">
28+
/// The <paramref name="builder"/> is <c>null</c>.
29+
/// </exception>
30+
/// <exception cref="ArgumentNullException">
31+
/// The <paramref name="storage"/> is <c>null</c>.
32+
/// </exception>
33+
/// <remarks>
34+
/// The <see cref="IServiceProvider"/> passed to the <paramref name="skipIf"/>
35+
/// is for the application services.
36+
/// </remarks>
37+
public static IRequestExecutorBuilder AddOpenApiDefinitionStorage(
38+
this IRequestExecutorBuilder builder,
39+
IOpenApiDefinitionStorage storage,
40+
Func<IServiceProvider, bool>? skipIf = null)
41+
{
42+
ArgumentNullException.ThrowIfNull(builder);
43+
ArgumentNullException.ThrowIfNull(storage);
44+
45+
builder.AddOpenApiDefinitionStorageCore(skipIf);
46+
47+
builder.Services.AddKeyedSingleton(builder.Name, storage);
48+
49+
return builder;
50+
}
51+
52+
/// <summary>
53+
/// Adds an OpenAPI definition storage to the gateway.
54+
/// </summary>
55+
/// <param name="builder">
56+
/// The <see cref="IRequestExecutorBuilder"/>.
57+
/// </param>
58+
/// <param name="skipIf">
59+
/// A function that is called to determine if the storage should be registered or not.
60+
/// If <c>true</c> is returned, the storage will not be registered.
61+
/// </param>
62+
/// <typeparam name="T">
63+
/// The type of the OpenAPI definition storage.
64+
/// </typeparam>
65+
/// <returns>
66+
/// Returns the <see cref="IRequestExecutorBuilder"/> so that configuration can be chained.
67+
/// </returns>
68+
/// <exception cref="ArgumentNullException">
69+
/// The <paramref name="builder"/> is <c>null</c>.
70+
/// </exception>
71+
/// <remarks>
72+
/// The <typeparamref name="T"/> will be activated with the <see cref="IServiceProvider"/> of the schema services.
73+
/// If your <typeparamref name="T"/> needs to access application services you need to
74+
/// make the services available in the schema services via <see cref="RequestExecutorBuilderExtensions.AddApplicationService"/>.
75+
/// <br />
76+
/// The <see cref="IServiceProvider"/> passed to the <paramref name="skipIf"/>
77+
/// is for the application services.
78+
/// </remarks>
79+
public static IRequestExecutorBuilder AddOpenApiDefinitionStorage<
80+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(
81+
this IRequestExecutorBuilder builder,
82+
Func<IServiceProvider, bool>? skipIf = null)
83+
where T : class, IOpenApiDefinitionStorage
84+
{
85+
ArgumentNullException.ThrowIfNull(builder);
86+
87+
builder.AddOpenApiDefinitionStorageCore(skipIf);
88+
89+
builder.Services.AddKeyedSingleton<IOpenApiDefinitionStorage, T>(builder.Name);
90+
91+
return builder;
92+
}
93+
94+
/// <summary>
95+
/// Adds an OpenAPI definition storage to the gateway.
96+
/// </summary>
97+
/// <param name="builder">
98+
/// The <see cref="IRequestExecutorBuilder"/>.
99+
/// </param>
100+
/// <param name="factory">
101+
/// The factory to create the OpenAPI definition storage.
102+
/// </param>
103+
/// <param name="skipIf">
104+
/// A function that is called to determine if the storage should be registered or not.
105+
/// If <c>true</c> is returned, the storage will not be registered.
106+
/// </param>
107+
/// <typeparam name="T">
108+
/// The type of the OpenAPI definition storage.
109+
/// </typeparam>
110+
/// <returns>
111+
/// Returns the <see cref="IRequestExecutorBuilder"/> so that configuration can be chained.
112+
/// </returns>
113+
/// <exception cref="ArgumentNullException">
114+
/// The <paramref name="builder"/> is <c>null</c>.
115+
/// </exception>
116+
/// <exception cref="ArgumentNullException">
117+
/// The <paramref name="factory"/> is <c>null</c>.
118+
/// </exception>
119+
/// <remarks>
120+
/// The <see cref="IServiceProvider"/> passed to the <paramref name="factory"/>
121+
/// is for the schema services. If you need to access application services
122+
/// you need to either make the services available in the schema services
123+
/// via <see cref="RequestExecutorBuilderExtensions.AddApplicationService"/> or use
124+
/// <see cref="ExecutionServiceProviderExtensions.GetRootServiceProvider(IServiceProvider)"/>
125+
/// to access the application services from within the schema service provider.
126+
/// <br />
127+
/// The <see cref="IServiceProvider"/> passed to the <paramref name="skipIf"/>
128+
/// is for the application services.
129+
/// </remarks>
130+
public static IRequestExecutorBuilder AddOpenApiDefinitionStorage<
131+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(
132+
this IRequestExecutorBuilder builder,
133+
Func<IServiceProvider, T> factory,
134+
Func<IServiceProvider, bool>? skipIf = null)
135+
where T : class, IOpenApiDefinitionStorage
136+
{
137+
ArgumentNullException.ThrowIfNull(builder);
138+
ArgumentNullException.ThrowIfNull(factory);
139+
140+
builder.AddOpenApiDefinitionStorageCore(skipIf);
141+
142+
builder.Services.AddKeyedSingleton<IOpenApiDefinitionStorage, T>(
143+
builder.Name,
144+
(sp, _) => factory(sp));
145+
146+
return builder;
147+
}
148+
149+
private static void AddOpenApiDefinitionStorageCore(
150+
this IRequestExecutorBuilder builder,
151+
Func<IServiceProvider, bool>? skipIf)
152+
{
153+
var schemaName = builder.Name;
154+
155+
builder.Services.AddOpenApiServices(schemaName);
156+
builder.Services.AddOpenApiAspNetCoreServices(schemaName);
157+
158+
builder.ConfigureSchemaServices((_, schemaServices) =>
159+
{
160+
schemaServices.TryAddSingleton<IOpenApiResultFormatter, OpenApiResultFormatter>();
161+
schemaServices.AddOpenApiSchemaServices();
162+
});
163+
164+
builder.AddWarmupTask(
165+
factory: schemaServices =>
166+
{
167+
var registry = schemaServices.GetRootServiceProvider()
168+
.GetRequiredKeyedService<OpenApiDefinitionRegistry>(schemaName);
169+
170+
return new OpenApiWarmupTask(registry);
171+
},
172+
skipIf: skipIf);
173+
}
174+
}

src/HotChocolate/Adapters/src/Adapters.OpenApi/Extensions/RequestExecutorBuilderExtensions.cs

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

src/HotChocolate/Adapters/src/Fusion.Adapters.OpenApi/Extensions/FusionGatewayBuilderExtensions.cs

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

0 commit comments

Comments
 (0)