Example #1
0
    private static async ValueTask <object?> ResolveManyNode(
        IResolverContext context,
        IIdSerializer serializer)
    {
        if (context.ArgumentKind(Ids) == ValueKind.List)
        {
            ListValueNode    list  = context.ArgumentLiteral <ListValueNode>(Ids);
            Task <object?>[] tasks = ArrayPool <Task <object?> > .Shared.Rent(list.Items.Count);

            var result = new object?[list.Items.Count];

            try
            {
                for (var i = 0; i < list.Items.Count; i++)
                {
                    context.RequestAborted.ThrowIfCancellationRequested();

                    // it is guaranteed that this is always a string literal.
                    StringValueNode nodeId         = (StringValueNode)list.Items[i];
                    IdValue         deserializedId = serializer.Deserialize(nodeId.Value);
                    NameString      typeName       = deserializedId.TypeName;

                    context.SetLocalValue(NodeId, nodeId.Value);
                    context.SetLocalValue(InternalId, deserializedId.Value);
                    context.SetLocalValue(InternalType, typeName);
                    context.SetLocalValue(WellKnownContextData.IdValue, deserializedId);

                    tasks[i] =
                        context.Schema.TryGetType <ObjectType>(typeName, out ObjectType? type) &&
                        type.ContextData.TryGetValue(NodeResolver, out var o) &&
                        o is FieldResolverDelegate resolver
                            ? resolver.Invoke(context).AsTask()
                            : _nullTask;
                }

                for (var i = 0; i < list.Items.Count; i++)
                {
                    context.RequestAborted.ThrowIfCancellationRequested();

                    Task <object?> task = tasks[i];
                    if (task.IsCompleted)
                    {
                        if (task.Exception is null)
                        {
                            result[i] = task.Result;
                        }
                        else
                        {
                            result[i] = null;
                            ReportError(context, i, task.Exception);
                        }
                    }
                    else
                    {
                        try
                        {
                            result[i] = await task;
                        }
                        catch (Exception ex)
                        {
                            result[i] = null;
                            ReportError(context, i, ex);
                        }
                    }
                }

                return(result);
            }
            finally
            {
                ArrayPool <Task <object?> > .Shared.Return(tasks);
            }
        }
        else
        {
            var result = new object?[1];
            result[0] = await ResolveSingleNode(context, serializer, Ids);

            return(result);
        }
    }