Skip to content

Commit

Permalink
Fusion Builder Refinements
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelstaib committed May 1, 2023
1 parent 8a1b877 commit e2274be
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 10 deletions.
@@ -0,0 +1,35 @@
using HotChocolate.Execution.Configuration;

namespace Microsoft.Extensions.DependencyInjection;

/// <summary>
/// A builder for configuring a GraphQL gateway.
/// </summary>
public sealed class FusionGatewayBuilder
{
/// <summary>
/// Initializes a new instance of <see cref="FusionGatewayBuilder"/>.
/// </summary>
/// <param name="coreBuilder">
/// The underlying request executor builder.
/// </param>
public FusionGatewayBuilder(IRequestExecutorBuilder coreBuilder)
{
CoreBuilder = coreBuilder;
}

/// <summary>
/// Gets the name of the schema.
/// </summary>
public string Name => CoreBuilder.Name;

/// <summary>
/// Gets the application services.
/// </summary>
public IServiceCollection Services => CoreBuilder.Services;

/// <summary>
/// Gets the underlying request executor builder.
/// </summary>
internal IRequestExecutorBuilder CoreBuilder { get; }
}
@@ -1,4 +1,5 @@
using HotChocolate;
using HotChocolate.Execution;
using HotChocolate.Execution.Configuration;
using HotChocolate.Fusion;
using HotChocolate.Fusion.Clients;
Expand All @@ -23,16 +24,20 @@ public static class FusionRequestExecutorBuilderExtensions
/// <param name="fusionGraphDocument">
/// The fusion graph document.
/// </param>
/// <param name="graphName">
/// The name of the fusion graph.
/// </param>
/// <returns>
/// Returns the <see cref="IRequestExecutorBuilder"/> that can be used to configure the Gateway.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/> is <c>null</c> or
/// <paramref name="fusionGraphDocument"/> is <c>null</c>.
/// </exception>
public static IRequestExecutorBuilder AddFusionGatewayServer(
public static FusionGatewayBuilder AddFusionGatewayServer(
this IServiceCollection services,
DocumentNode fusionGraphDocument)
DocumentNode fusionGraphDocument,
string? graphName = default)
{
if (services is null)
{
Expand All @@ -45,7 +50,8 @@ public static class FusionRequestExecutorBuilderExtensions
}

return services.AddFusionGatewayServer(
_ => new ValueTask<DocumentNode>(fusionGraphDocument));
_ => new ValueTask<DocumentNode>(fusionGraphDocument),
graphName: graphName);
}

/// <summary>
Expand All @@ -57,6 +63,9 @@ public static class FusionRequestExecutorBuilderExtensions
/// <param name="fusionGraphFile">
/// The path to the fusion graph package file or fusion graph file.
/// </param>
/// <param name="graphName">
/// The name of the fusion graph.
/// </param>
/// <param name="watchFileForUpdates">
/// If set to <c>true</c> the fusion graph file will be watched for updates and
/// the schema is rebuild whenever the file changes.
Expand All @@ -69,9 +78,10 @@ public static class FusionRequestExecutorBuilderExtensions
/// <paramref name="fusionGraphFile"/> is <c>null</c> or
/// <paramref name="fusionGraphFile"/> is equals to <see cref="string.Empty"/>.
/// </exception>
public static IRequestExecutorBuilder AddFusionGatewayServer(
public static FusionGatewayBuilder AddFusionGatewayServer(
this IServiceCollection services,
string fusionGraphFile,
string? graphName = default,
bool watchFileForUpdates = false)
{
if (services is null)
Expand All @@ -84,11 +94,13 @@ public static class FusionRequestExecutorBuilderExtensions
throw new ArgumentNullException(nameof(fusionGraphFile));
}

var builder = services.AddFusionGatewayServer(ct => LoadDocumentAsync(fusionGraphFile, ct));
var builder = services.AddFusionGatewayServer(
ct => LoadDocumentAsync(fusionGraphFile, ct),
graphName: graphName);

if (watchFileForUpdates)
{
builder.AddTypeModule(_ => new FileWatcherTypeModule(fusionGraphFile));
builder.CoreBuilder.AddTypeModule(_ => new FileWatcherTypeModule(fusionGraphFile));
}

return builder;
Expand All @@ -103,16 +115,20 @@ public static class FusionRequestExecutorBuilderExtensions
/// <param name="fusionGraphResolver">
/// A delegate that is used to resolve a fusion graph document.
/// </param>
/// <param name="graphName">
/// The name of the fusion graph.
/// </param>
/// <returns>
/// Returns the <see cref="IRequestExecutorBuilder"/> that can be used to configure the Gateway.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="services"/> is <c>null</c> or
/// <paramref name="fusionGraphResolver"/> is <c>null</c>.
/// </exception>
public static IRequestExecutorBuilder AddFusionGatewayServer(
public static FusionGatewayBuilder AddFusionGatewayServer(
this IServiceCollection services,
ResolveFusionGraphDocAsync fusionGraphResolver)
ResolveFusionGraphDocAsync fusionGraphResolver,
string? graphName = default)
{
if (services is null)
{
Expand All @@ -124,8 +140,8 @@ public static class FusionRequestExecutorBuilderExtensions
throw new ArgumentNullException(nameof(fusionGraphResolver));
}

return services
.AddGraphQLServer()
var builder = services
.AddGraphQLServer(graphName)
.UseField(next => next)
.UseDefaultGatewayPipeline()
.AddOperationCompilerOptimizer<OperationQueryPlanCompiler>()
Expand Down Expand Up @@ -157,6 +173,8 @@ public static class FusionRequestExecutorBuilderExtensions
sc.TryAddSingleton<QueryPlanner>();
});
});

return new FusionGatewayBuilder(builder);
}

private static IRequestExecutorBuilder UseDefaultGatewayPipeline(
Expand Down Expand Up @@ -238,6 +256,45 @@ public static class FusionRequestExecutorBuilderExtensions
return Utf8GraphQLParser.Parse(sourceText);
}
}

/// <summary>
/// Builds a <see cref="IRequestExecutor"/> from the specified
/// <see cref="FusionGatewayBuilder"/>.
/// </summary>
/// <param name="builder">
/// The <see cref="FusionGatewayBuilder"/>.
/// </param>
/// <param name="graphName">
/// The name of the graph that shall be built.
/// </param>
/// <param name="cancellationToken">
/// The cancellation token.
/// </param>
/// <returns></returns>
internal static ValueTask<IRequestExecutor> BuildRequestExecutorAsync(
this FusionGatewayBuilder builder,
string? graphName = default,
CancellationToken cancellationToken = default)
=> builder.CoreBuilder.BuildRequestExecutorAsync(graphName, cancellationToken);

/// <summary>
/// Builds a <see cref="ISchema"/> from the specified <see cref="FusionGatewayBuilder"/>.
/// </summary>
/// <param name="builder">
/// The <see cref="FusionGatewayBuilder"/>.
/// </param>
/// <param name="graphName">
/// The name of the graph that shall be built.
/// </param>
/// <param name="cancellationToken">
/// The cancellation token.
/// </param>
/// <returns></returns>
internal static ValueTask<ISchema> BuildSchemaAsync(
this FusionGatewayBuilder builder,
string? graphName = default,
CancellationToken cancellationToken = default)
=> builder.CoreBuilder.BuildSchemaAsync(graphName, cancellationToken);
}

static file class FileExtensions
Expand Down
Expand Up @@ -946,6 +946,7 @@ public async Task Hot_Reload()
.AddSingleton(demoProject.HttpClientFactory)
.AddSingleton(demoProject.WebSocketConnectionFactory)
.AddFusionGatewayServer(_ => new(SchemaFormatter.FormatAsDocument(fusionGraph)))
.CoreBuilder
.AddTypeModule(_ => reloadTypeModule)
.Services
.BuildServiceProvider();
Expand Down

0 comments on commit e2274be

Please sign in to comment.