public static Resolver DefaultCreateRemoteResolver(ExecutionResultLink link) { return(async context => { var document = CreateDocument(context); var variables = context.ExecutionContext.CoercedVariableValues; var reader = await link(document, variables, CancellationToken.None); while (await reader.WaitToReadAsync(CancellationToken.None)) { if (reader.TryRead(out var executionResult)) { return new PreExecutedResolverResult(executionResult); } } throw new QueryExecutionException( "Could not get result from remote. " + "Link channel was closed before result could be read.", context.Path, context.Selection); }); ExecutableDocument CreateDocument(IResolverContext context) { return(context.ExecutionContext.Document); } }
private static Subscriber DefaultCreateRemoteSubscriber(ExecutionResultLink link) { return(async(context, unsubscribe) => { var document = CreateDocument(context); var variables = context.ExecutionContext.CoercedVariableValues; var result = await link(document, variables, unsubscribe); var stream = new EventChannel <ExecutionResult>(); var _ = Task.Run(async() => { while (await result.WaitToReadAsync(unsubscribe)) { if (result.TryRead(out var executionResult)) { await stream.WriteAsync( executionResult); } } await result.Completion; }, unsubscribe); return Resolve.Subscribe(stream, unsubscribe); }); GraphQLDocument CreateDocument(ResolverContext context) { return(context.ExecutionContext.Document); } }
/// <summary> /// Execute <see cref="Introspect.DefaultQuery"/> on link /// and import the schema /// </summary> /// <param name="builder"></param> /// <param name="link">Execution link</param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task <SchemaBuilder> ImportIntrospectedSchema( this SchemaBuilder builder, ExecutionResultLink link, CancellationToken cancellationToken = default) { if (link == null) { throw new ArgumentNullException(nameof(link)); } var channel = await link( Parser.ParseDocument(Introspect.DefaultQuery), null, cancellationToken); var result = await channel.ReadAsync(cancellationToken); if (result.Errors != null && result.Errors.Any()) { throw new InvalidOperationException( "Failed to execute introspection query. " + $"Errors: {string.Join(", ", result.Errors.Select(e => e.Message))}"); } var json = JsonConvert.SerializeObject(result); return(ImportIntrospectedSchema(builder, json)); }
//todo: use ResolversBuilder.AddLinkedTypes() /// <summary> /// Create resolvers for ObjectTypes and ObjectType extensions in <see cref="TypeSystemDocument"/> which /// resolve the values using the given <paramref name="link"/> /// </summary> /// <param name="remoteTypes"></param> /// <param name="link"></param> /// <param name="createResolver"></param> /// <param name="createSubscriber"></param> /// <returns></returns> public static ResolversMap CreateLinkResolvers( TypeSystemDocument remoteTypes, ExecutionResultLink link, Func <ExecutionResultLink, Resolver> createResolver = null, Func <ExecutionResultLink, Subscriber> createSubscriber = null) { if (createResolver == null) { createResolver = DefaultCreateRemoteResolver; } if (createSubscriber == null) { createSubscriber = DefaultCreateRemoteSubscriber; } var objectDefinitionsAndExtensions = GetObjectDefinitions(remoteTypes); var rootTypes = objectDefinitionsAndExtensions.Where(type => RootTypes.Contains(type.Name.Value)) .OfType <ObjectDefinition>(); ResolversMap resolvers = new ResolversMap(); foreach (var rootType in rootTypes) { foreach (var field in rootType.Fields) { if (rootType.Name != "Subscription") { resolvers.Add(rootType.Name.Value, field.Name.Value, createResolver(link)); } else { resolvers.Add(rootType.Name.Value, field.Name.Value, createSubscriber(link)); } } } var resolver = DefaultDictionaryResolver(); foreach (var objectType in objectDefinitionsAndExtensions.Where(type => !RootTypes.Contains(type.Name.Value)) .OfType <ObjectDefinition>()) { foreach (var field in objectType.Fields) { resolvers.Add(objectType.Name.Value, field.Name.Value, resolver); } } return(resolvers); }
public static Resolver DefaultCreateRemoteResolver(ExecutionResultLink link) { return(async context => { var document = CreateDocument(context); var variables = context.ExecutionContext.CoercedVariableValues; var reader = await link(document, variables, CancellationToken.None); while (await reader.WaitToReadAsync(CancellationToken.None)) { if (reader.TryRead(out var executionResult)) { if (executionResult.Errors != null && executionResult.Errors.Any()) { var first = executionResult.Errors.First(); throw new QueryExecutionException( $"{first.Message}", null, path: context.Path, extensions: new Dictionary <string, object> { ["remoteError"] = new { data = executionResult.Data, errors = executionResult.Errors, extensions = executionResult.Extensions } }, context.Selection); } return new PreExecutedResolveResult(executionResult.Data); } } throw new QueryExecutionException( "Could not get result from remote. " + "Link channel was closed before result could be read.", context.Path, context.Selection); }); GraphQLDocument CreateDocument(ResolverContext context) { return(context.ExecutionContext.Document); } }
public static Resolver DefaultCreateRemoteResolver(ExecutionResultLink link) { return(async context => { var document = CreateDocument(context); var variables = context.ExecutionContext.CoercedVariableValues; var reader = await link(document, variables, CancellationToken.None); while (await reader.WaitToReadAsync(CancellationToken.None)) { if (reader.TryRead(out var executionResult)) { if (executionResult.Errors != null && executionResult.Errors.Any()) { var first = executionResult.Errors.First(); throw new CompleteValueException( $"{first.Message}", new[] { context.Selection }, locations: new[] { context.Selection.Location }, path: context.Path, extensions: new Dictionary <string, object> { ["remoteError"] = new { data = executionResult.Data, errors = executionResult.Errors, extensions = executionResult.Extensions } }); } return new PreExecutedResolveResult(executionResult.Data); } } //todo return null; }); GraphQLDocument CreateDocument(ResolverContext context) { return(context.ExecutionContext.Document); } }
/// <summary> /// Execute <see cref="Introspect.DefaultQuery" /> on link /// and import the schema /// </summary> /// <param name="builder"></param> /// <param name="link">Execution link</param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task <SchemaBuilder> ImportIntrospectedSchema( this SchemaBuilder builder, ExecutionResultLink link, CancellationToken cancellationToken = default) { if (link == null) { throw new ArgumentNullException(nameof(link)); } var channel = await link( Introspect.DefaultQuery, null, cancellationToken); if (channel == null) { throw new InvalidOperationException( "Failed to execute introspection query. Link returned a null channel."); } var result = await channel.ReadAsync(cancellationToken); if (result == null) { throw new InvalidOperationException( "Failed to execute introspection query. Link channel read result is null"); } if (result.Errors != null && result.Errors.Any()) { throw new InvalidOperationException( "Failed to execute introspection query. " + $"Errors: {string.Join(", ", result.Errors.Select(e => e.Message))}"); } var json = JsonSerializer.Serialize(result, _jsonOptions); return(builder.AddIntrospectedSchema(json)); }
public static ISchema MakeRemoteExecutable( SchemaBuilder builder, ExecutionResultLink link, Func <ExecutionResultLink, Resolver> createResolver = null, Func <ExecutionResultLink, Subscriber> createSubscriber = null) { if (createResolver == null) { createResolver = DefaultCreateRemoteResolver; } if (createSubscriber == null) { createSubscriber = DefaultCreateRemoteSubscriber; } // add remote resolver for query if (builder.TryGetType <ObjectType>("Query", out var queryType)) { builder.Connections(connections => { var fields = connections.VisitFields(queryType); foreach (var field in fields) { var resolver = connections.GetOrAddResolver(queryType, field.Key); resolver.Run(createResolver(link)); } }); } if (builder.TryGetType <ObjectType>("Mutation", out var mutationType)) { builder.Connections(connections => { var fields = connections.VisitFields(mutationType); foreach (var field in fields) { var resolver = connections.GetOrAddResolver(mutationType, field.Key); resolver.Run(createResolver(link)); } }); } if (builder.TryGetType <ObjectType>("Subscription", out var subscriptionType)) { builder.Connections(connections => { var fields = connections.VisitFields(subscriptionType); foreach (var field in fields) { if (!connections.TryGetSubscriber(subscriptionType, field.Key, out _)) { var subscriber = connections.GetOrAddSubscriber(subscriptionType, field.Key); subscriber.Run(createSubscriber(link)); } } }); } foreach (var objectType in builder.VisitTypes <ObjectType>()) { builder.Connections(connections => { foreach (var field in connections.VisitFields(objectType)) { if (!connections.TrGetResolver(objectType, field.Key, out _)) { var resolver = connections.GetOrAddResolver(objectType, field.Key); resolver.Run(DefaultDictionaryResolver()); } } }); } return(builder.Build()); }