/// <summary>
        /// Adds or replaces the source data supplied to the field request.
        /// </summary>
        /// <param name="sourceData">The source data.</param>
        /// <param name="path">An optional to mock where in the graph query the data originated.</param>
        /// <returns>MockFieldRequest.</returns>
        public FieldContextBuilder AddSourceData(object sourceData, SourcePath path = null)
        {
            path = path ?? SourcePath.None;
            var item       = new GraphDataItem(_mockInvocationContext.Object, sourceData, path);
            var dataSource = new GraphFieldDataSource(sourceData, path, item);

            _mockRequest.Setup(x => x.DataSource).Returns(dataSource);
            return(this);
        }
Пример #2
0
        private void CreateEdge(GraphDataItem item)
        {
            var edge = new Edge
            {
                ID           = item.EdgeID,
                SourceVertex = EnsureVertex(item.SourceVertexID),
                TargetVertex = EnsureVertex(item.TargetVertexID),
                Cost         = item.Cost,
                IsReverse    = false,
                DataItem     = item,
            };

            edge.SourceVertex.Neighbours.Add(edge.TargetVertex);
            {
                var key = GetKey(edge.SourceVertex.ID, edge.TargetVertex.ID);
                if (!mEdges.ContainsKey(key))
                {
                    mEdges.Add(key, edge);
                }
                else if (mEdges[key].Cost > edge.Cost)
                {
                    mEdges[key] = edge;
                }
            }

            edge = new Edge
            {
                ID           = item.EdgeID,
                SourceVertex = EnsureVertex(item.TargetVertexID),
                TargetVertex = EnsureVertex(item.SourceVertexID),
                Cost         = item.ReverseCost,
                IsReverse    = true,
                DataItem     = item,
            };
            edge.SourceVertex.Neighbours.Add(edge.TargetVertex);
            {
                var key = GetKey(edge.SourceVertex.ID, edge.TargetVertex.ID);
                if (!mEdges.ContainsKey(key))
                {
                    mEdges.Add(key, edge);
                }
                else if (mEdges[key].Cost > edge.Cost)
                {
                    mEdges[key] = edge;
                }
            }
        }
        private void OnTimerTick(object sender, EventArgs e)
        {
            if (GraphCanvas.ActualWidth == 0 || GraphCanvas.ActualHeight == 0)
            {
                return;
            }

            if (m_updateGraphBorder)
            {
                UpdateGraphBorders();
                m_updateGraphBorder = false;
            }

            DateTime now = DateTime.Now;

            List <GraphDataItem> tempList = new List <GraphDataItem>(m_graphData);

            foreach (GraphDataItem dataItem in tempList)
            {
                if (m_graphData.Count == 1)
                {
                    break;
                }

                TimeSpan timeElapsed = now - dataItem.time;
                if (timeElapsed.TotalMilliseconds > GRAPH_TIME_LENGTH_MSEC)
                {
                    GraphCanvas.Children.Remove(dataItem.graphBar);
                    m_graphData.Remove(dataItem);
                }
            }

            double xScale  = (GraphCanvas.ActualWidth - GRAPH_X_MARGIN * 2.0) / GRAPH_TIME_LENGTH_MSEC;
            double yScale  = (GraphCanvas.ActualHeight - GRAPH_Y_MARGIN * 2.0) / (m_yMax - m_yMin);
            double xOffset = GraphCanvas.ActualWidth - 2.0 * GRAPH_X_MARGIN;

            Debug.Assert(xScale > 0.0);
            Debug.Assert(yScale > 0.0);
            Debug.Assert(xOffset > 0.0);

            for (int i = m_graphData.Count - 1; i >= 0; --i)
            {
                GraphDataItem graphDataItem = m_graphData[i];

                DateTime endTime  = (i == m_graphData.Count - 1) ? now : m_graphData[i + 1].time;
                double   duration = (endTime - graphDataItem.time).TotalMilliseconds;

                graphDataItem.graphBar.Width  = Math.Min(duration * xScale, GRAPH_TIME_LENGTH_MSEC * xScale);
                graphDataItem.graphBar.Width  = Math.Min(graphDataItem.graphBar.Width, xOffset);
                graphDataItem.graphBar.Height = graphDataItem.val * yScale;
                graphDataItem.graphBar.SetValue(Canvas.LeftProperty, GRAPH_X_MARGIN + xOffset - graphDataItem.graphBar.Width);
                graphDataItem.graphBar.SetValue(Canvas.TopProperty, GraphCanvas.ActualHeight - GRAPH_Y_MARGIN - graphDataItem.graphBar.Height);

                if (!GraphCanvas.Children.Contains(graphDataItem.graphBar))
                {
                    GraphCanvas.Children.Insert(GraphCanvas.Children.Count - 1, graphDataItem.graphBar);
                }

                xOffset = xOffset - graphDataItem.graphBar.Width;

                if (xOffset < Double.Epsilon)
                {
                    break;
                }
            }
        }
Пример #4
0
        private async Task ExecuteOperation(GraphQueryExecutionContext context)
        {
            // create a cancelation sourc irrespective of the required timeout for exeucting this operation
            // this allows for indication of why a task was canceled (timeout or other user driven reason)
            // vs just "it was canceled" which allows for tighter error messages in the response.
            var operation        = context.QueryOperation;
            var fieldInvocations = new List <FieldPipelineInvocation>();

            // Convert the supplied variable values to usable objects of the type expression
            // of the chosen operation
            var variableResolver = new ResolvedVariableGenerator(_schema, operation);
            var variableData     = variableResolver.Resolve(context.Request.VariableData);
            var cancelSource     = new CancellationTokenSource();

            try
            {
                // begin a field execution pipeline for each top level field
                foreach (var invocationContext in operation.FieldContexts)
                {
                    var path = new SourcePath();
                    path.AddFieldName(invocationContext.Name);

                    object dataSourceValue;

                    // fetch the source data value to use for the field invocation
                    // attempt to retrieve from the master context if it was supplied by the pipeline
                    // invoker, otherwise generate a root source
                    if (!context.DefaultFieldSources.TryRetrieveSource(invocationContext.Field, out dataSourceValue))
                    {
                        dataSourceValue = this.GenerateRootSourceData(operation.OperationType);
                    }

                    var topLevelDataItem = new GraphDataItem(invocationContext, dataSourceValue, path);

                    var sourceData = new GraphFieldDataSource(dataSourceValue, path, topLevelDataItem);

                    var fieldRequest = new GraphFieldRequest(
                        invocationContext,
                        sourceData,
                        new SourceOrigin(invocationContext.Origin.Location, path),
                        context.Items);

                    var fieldContext = new GraphFieldExecutionContext(
                        context,
                        fieldRequest,
                        variableData,
                        context.DefaultFieldSources);

                    var fieldTask = _fieldExecutionPipeline.InvokeAsync(fieldContext, cancelSource.Token);

                    var pipelineInvocation = new FieldPipelineInvocation()
                    {
                        Task         = fieldTask,
                        DataItem     = topLevelDataItem,
                        FieldContext = fieldContext,
                    };

                    fieldInvocations.Add(pipelineInvocation);

                    // top level mutation operatons must be executed in sequential order
                    // https://graphql.github.io/graphql-spec/June2018/#sec-Mutation
                    if (_awaitEachTask || operation.OperationType == GraphCollection.Mutation)
                    {
                        await fieldTask.ConfigureAwait(false);
                    }
                }

                // await all the outstanding tasks or a configured timeout
                var fieldPipelineTasksWrapper = Task.WhenAll(fieldInvocations.Select(x => x.Task));
                var timeOutTask = Task.Delay(_timeoutMs, cancelSource.Token);

                var completedTask = await Task.WhenAny(fieldPipelineTasksWrapper, timeOutTask).ConfigureAwait(false);

                var isTimedOut = completedTask == timeOutTask;
                var cancelationWasRequested = cancelSource.IsCancellationRequested;

                if (!isTimedOut)
                {
                    // Field resolutions completed within the timeout period.
                    // Consider that the task may have faulted or been canceled causing them to complete incorrectly.
                    // "re-await" so that any exceptions/cancellation are rethrown correctly.
                    // and not aggregated under the `WhenAll/WhenAny` task from above
                    // https://stackoverflow.com/questions/4238345/asynchronously-wait-for-taskt-to-complete-with-timeout
                    foreach (var invocation in fieldInvocations)
                    {
                        await invocation.Task.ConfigureAwait(false);

                        // load the reslts of each field (in order) to the context
                        // for further processing
                        context.FieldResults.Add(invocation.DataItem);
                        context.Messages.AddRange(invocation.FieldContext.Messages);
                    }
                }
                else
                {
                    // when the timeout finishes first, process the cancel token in case any outstanding tasks are running
                    // helps in cases where the timeout finished first but any of the field resolutions are perhaps stuck open
                    // instruct all outstanding tasks to clean them selves up at the earlest possible point
                    if (!cancelationWasRequested)
                    {
                        cancelSource.Cancel();
                    }
                }

                if (cancelationWasRequested)
                {
                    context.Messages.Critical("The execution was canceled prior to completion of the requested query.", Constants.ErrorCodes.OPERATION_CANCELED);
                }
                else if (isTimedOut)
                {
                    context.Messages.Critical($"The execution timed out prior to completion of the requested query. (Total Time: {_timeoutMs}ms)", Constants.ErrorCodes.OPERATION_CANCELED);
                }
            }
            finally
            {
                cancelSource.Dispose();
            }
        }
Пример #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="FieldValidationContext" /> class.
 /// </summary>
 /// <param name="schema">The schema in scope for this validation context.</param>
 /// <param name="dataItem">The data item to process.</param>
 /// <param name="messageCollection">An optional message collection to use for this context, if not supplied
 /// a new one will be generated.</param>
 public FieldValidationContext(ISchema schema, GraphDataItem dataItem, IGraphMessageCollection messageCollection = null)
 {
     this.Schema   = Validation.ThrowIfNullOrReturn(schema, nameof(schema));
     this.DataItem = dataItem;
     this.Messages = messageCollection ?? new GraphMessageCollection();
 }