Skip to content

Commit

Permalink
Builders refactoring (#1572)
Browse files Browse the repository at this point in the history
* Moving extensions aroun
  • Loading branch information
pekkah authored Mar 10, 2023
1 parent 2fb7f80 commit a2c3ea9
Show file tree
Hide file tree
Showing 66 changed files with 271 additions and 293 deletions.
1 change: 1 addition & 0 deletions benchmarks/graphql.benchmarks/ExecutionBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Extensions.Logging.Abstractions;
using Tanka.GraphQL.Fields;
using Tanka.GraphQL.Language.Nodes;
using Tanka.GraphQL.Request;
using Tanka.GraphQL.SelectionSets;
using Tanka.GraphQL.TypeSystem;
using Tanka.GraphQL.Validation;
Expand Down
3 changes: 2 additions & 1 deletion dev/graphql.dev.chat.data/ChatResolvers.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Tanka.GraphQL.Samples.Chat.Data.Domain;
using Tanka.GraphQL.Executable;
using Tanka.GraphQL.Samples.Chat.Data.Domain;
using Tanka.GraphQL.Server;
using Tanka.GraphQL.ValueResolution;

Expand Down
1 change: 0 additions & 1 deletion dev/graphql.dev.chat.data/IChat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Threading.Channels;
using System.Threading.Tasks;
using Tanka.GraphQL.Samples.Chat.Data.Domain;
using Tanka.GraphQL.Subscriptions;

namespace Tanka.GraphQL.Samples.Chat.Data;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Tanka.GraphQL.Extensions.ApolloFederation;
using Tanka.GraphQL.Executable;

namespace Tanka.GraphQL.Extensions.ApolloFederation;

public static class FederationExecutableSchemaBuilderExtensions
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Tanka.GraphQL.Executable;
using Tanka.GraphQL.Fields;
using Tanka.GraphQL.Language;
using Tanka.GraphQL.Language.Nodes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Immutable;
using System.Threading.Channels;

namespace Tanka.GraphQL.Subscriptions;
namespace Tanka.GraphQL;

public class BroadcastChannel<T> : IAsyncDisposable
{
Expand Down
135 changes: 30 additions & 105 deletions src/GraphQL/DefaultOperationPipelineBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,44 +1,43 @@
using Tanka.GraphQL.Extensions.Trace;
using Tanka.GraphQL.Execution;
using Tanka.GraphQL.Extensions.Trace;
using Tanka.GraphQL.Features;
using Tanka.GraphQL.Language.Nodes;
using Tanka.GraphQL.Request;
using Tanka.GraphQL.SelectionSets;
using Tanka.GraphQL.Validation;
using Tanka.GraphQL.ValueResolution;

namespace Tanka.GraphQL;

public static class DefaultOperationDelegateBuilderExtensions
{
public static OperationDelegateBuilder AddFeature<TFeature>(this OperationDelegateBuilder builder, TFeature feature)
public static OperationDelegateBuilder AddDefaultFeatures(
this OperationDelegateBuilder builder)
{
var errorFeature = new ConcurrentBagErrorCollectorFeature();
var argumentBinderFeature = new ArgumentBinderFeature();
var defaultSelectionSetExecutorFeature = new DefaultSelectionSetExecutorFeature();
var fieldExecutorFeature = new FieldExecutorFeature();
var valueCompletionFeature = new ValueCompletionFeature();

return builder.Use(next => context =>
{
context.Features.Set<TFeature>(feature);
context.Features.Set<IErrorCollectorFeature>(errorFeature);
context.Features.Set<IArgumentBinderFeature>(argumentBinderFeature);
context.Features.Set<ISelectionSetExecutorFeature>(defaultSelectionSetExecutorFeature);
context.Features.Set<IFieldExecutorFeature>(fieldExecutorFeature);
context.Features.Set<IValueCompletionFeature>(valueCompletionFeature);
return next(context);
});
}

public static OperationDelegateBuilder AddDefaultErrorCollectorFeature(
this OperationDelegateBuilder builder)
public static OperationDelegateBuilder RunQueryOrMutation(this OperationDelegateBuilder builder)
{
var feature = new ConcurrentBagErrorCollectorFeature();
return builder.Use(next => context =>
{
context.Features.Set<IErrorCollectorFeature>(feature);
return next(context);
});
return builder.Use(_ => async context => { await Executor.ExecuteQueryOrMutation(context); });
}



public static OperationDelegateBuilder AddDefaultArgumentBinderFeature(
this OperationDelegateBuilder builder)
public static OperationDelegateBuilder RunSubscription(this OperationDelegateBuilder builder)
{
var feature = new ArgumentBinderFeature();
return builder.Use(next => context =>
{
context.Features.Set<IArgumentBinderFeature>(feature);
return next(context);
});
return builder.Use(_ => async context => { await Executor.ExecuteSubscription(context); });
}

public static OperationDelegateBuilder UseDefaultOperationResolver(this OperationDelegateBuilder builder)
Expand All @@ -62,47 +61,33 @@ public static OperationDelegateBuilder UseDefaultOperationResolver(this Operatio
/// <returns></returns>
public static OperationDelegateBuilder UseDefaults(this OperationDelegateBuilder builder)
{
if (builder.GetProperty<bool>("TraceEnabled"))
{
builder.UseTrace();
}
if (builder.GetProperty<bool>("TraceEnabled")) builder.UseTrace();

// extend query context with required features
builder.AddDefaultErrorCollectorFeature();

builder.AddDefaultSelectionSetExecutorFeature();
builder.AddDefaultFieldExecutorFeature();
builder.AddDefaultValueCompletionFeature();
builder.AddDefaultFeatures();

// actual flow
builder.UseDefaultValidator();
builder.UseDefaultOperationResolver();
builder.UseDefaultVariableCoercer();
builder.WhenOperationTypeUse(query =>
{
query.RunQueryOrMutation();
},
mutation =>
{
mutation.RunQueryOrMutation();
},
subscriptions =>
{
subscriptions.RunSubscription();
});
builder.WhenOperationTypeIsUse(
query => { query.RunQueryOrMutation(); },
mutation => { mutation.RunQueryOrMutation(); },
subscriptions => { subscriptions.RunSubscription(); }
);

return builder;
}



public static OperationDelegateBuilder UseDefaultValidator(this OperationDelegateBuilder builder)
{
var validator = new Validator3(ExecutionRules.All);

builder.Use(next => async context =>
{
var result = await validator.Validate(context.Schema, context.Request.Document, context.Request.Variables);
ValidationResult result =
await validator.Validate(context.Schema, context.Request.Document, context.Request.Variables);

if (!result.IsValid)
throw new ValidationException(result);
Expand All @@ -113,17 +98,6 @@ public static OperationDelegateBuilder UseDefaultValidator(this OperationDelegat
return builder;
}

public static OperationDelegateBuilder AddDefaultValueCompletionFeature(
this OperationDelegateBuilder builder)
{
var feature = new ValueCompletionFeature();
return builder.Use(next => context =>
{
context.Features.Set<IValueCompletionFeature>(feature);
return next(context);
});
}

public static OperationDelegateBuilder UseDefaultVariableCoercer(this OperationDelegateBuilder builder)
{
builder.Use(next => context =>
Expand All @@ -138,53 +112,4 @@ public static OperationDelegateBuilder UseDefaultVariableCoercer(this OperationD

return builder;
}

public static OperationDelegateBuilder WhenOperationTypeUse(
this OperationDelegateBuilder builder,
Action<OperationDelegateBuilder> queryAction,
Action<OperationDelegateBuilder> mutationAction,
Action<OperationDelegateBuilder> subscriptionAction)
{
var queryBuilder = new OperationDelegateBuilder(builder.ApplicationServices);
queryAction(queryBuilder);
var queryDelegate = queryBuilder.Build();

var mutationBuilder = new OperationDelegateBuilder(builder.ApplicationServices);
mutationAction(mutationBuilder);
var mutationDelegate = mutationBuilder.Build();

var subscriptionBuilder = new OperationDelegateBuilder(builder.ApplicationServices);
subscriptionAction(subscriptionBuilder);
var subscriptionDelegate = subscriptionBuilder.Build();

return builder.Use(_ => async context =>
{
Task execute = context.OperationDefinition.Operation switch
{
OperationType.Query => queryDelegate(context),
OperationType.Mutation => mutationDelegate(context),
OperationType.Subscription => subscriptionDelegate(context),
_ => throw new InvalidOperationException(
$"Operation type {context.OperationDefinition.Operation} not supported.")
};

await execute;
});
}

public static OperationDelegateBuilder RunQueryOrMutation(this OperationDelegateBuilder builder)
{
return builder.Use(_ => async context =>
{
await Executor.ExecuteQueryOrMutation(context);
});
}

public static OperationDelegateBuilder RunSubscription(this OperationDelegateBuilder builder)
{
return builder.Use(_ => async context =>
{
await Executor.ExecuteSubscription(context);
});
}
}
6 changes: 0 additions & 6 deletions src/GraphQL/DefaultResponseStreamFeature.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Concurrent;
using Tanka.GraphQL.Features;

namespace Tanka.GraphQL.Features;
namespace Tanka.GraphQL;

public class ConcurrentBagErrorCollectorFeature : IErrorCollectorFeature
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Tanka.GraphQL.ValueResolution;
using Tanka.GraphQL.ValueSerialization;

namespace Tanka.GraphQL;
namespace Tanka.GraphQL.Executable;

public class ExecutableSchemaBuilder
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Tanka.GraphQL.ValueResolution;

namespace Tanka.GraphQL;
namespace Tanka.GraphQL.Executable;

public interface IExecutableSchemaConfiguration
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Tanka.GraphQL.Language.Nodes.TypeSystem;
using Tanka.GraphQL.ValueResolution;

namespace Tanka.GraphQL;
namespace Tanka.GraphQL.Executable;

public class ObjectResolversConfiguration : IExecutableSchemaConfiguration
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Tanka.GraphQL.Language.Nodes.TypeSystem;
using Tanka.GraphQL.ValueResolution;

namespace Tanka.GraphQL;
namespace Tanka.GraphQL.Executable;

public class ObjectSubscribersConfiguration : IExecutableSchemaConfiguration
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Tanka.GraphQL.ValueResolution;

namespace Tanka.GraphQL;
namespace Tanka.GraphQL.Executable;

public class ResolversConfiguration : IExecutableSchemaConfiguration
{
Expand All @@ -14,12 +14,12 @@ public ResolversConfiguration(IResolverMap resolversMap)
public Task Configure(SchemaBuilder schema, ResolversBuilder resolvers)
{
foreach (var (typeName, fields) in _resolversMap.GetTypes())
foreach (var field in fields)
{
var resolver = _resolversMap.GetResolver(typeName, field);
if (resolver is not null)
resolvers.Add(typeName, field, r => r.Run(resolver));
}
foreach (var field in fields)
{
var resolver = _resolversMap.GetResolver(typeName, field);
if (resolver is not null)
resolvers.Add(typeName, field, r => r.Run(resolver));
}

return Task.CompletedTask;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
namespace Tanka.GraphQL;
using Tanka.GraphQL.Features;

namespace Tanka.GraphQL.Execution;

public static class FieldExecutionOperationDelegateBuilderExtensions
{
public static OperationDelegateBuilder AddDefaultFieldExecutorFeature(
this OperationDelegateBuilder builder)
{
var feature = new FieldExecutorFeature();
return builder.Use(next => context =>
{
context.Features.Set<IFieldExecutorFeature>(feature);
return next(context);
});
}

public static OperationDelegateBuilder AddFieldDelegateExecutorFeature(
this OperationDelegateBuilder builder,
Action<FieldDelegateBuilder> configureFieldExecutor)
{
var fieldDelegateBuilder = new FieldDelegateBuilder(builder.ApplicationServices);
configureFieldExecutor(fieldDelegateBuilder);

var feature = new FieldPipelineExecutorFeature(fieldDelegateBuilder.Build());
return builder.Use(next => context =>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Tanka.GraphQL.Language.Nodes;
using Tanka.GraphQL.Features;
using Tanka.GraphQL.Language.Nodes;

namespace Tanka.GraphQL.Features;
namespace Tanka.GraphQL.Execution;

public class OperationFeature : IOperationFeature
{
Expand Down
Loading

0 comments on commit a2c3ea9

Please sign in to comment.