-
-
Notifications
You must be signed in to change notification settings - Fork 736
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ExecutionContext & Task Statistics (#1959)
- Loading branch information
1 parent
76d21ee
commit d00a8f8
Showing
13 changed files
with
759 additions
and
65 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
src/HotChocolate/Core/src/Execution/ExecutionContext.Pooling.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using HotChocolate.Fetching; | ||
using HotChocolate.Execution.Utilities; | ||
using Microsoft.Extensions.ObjectPool; | ||
using System; | ||
|
||
namespace HotChocolate.Execution | ||
{ | ||
internal partial class ExecutionContext : IExecutionContext | ||
{ | ||
public void Reset() | ||
{ | ||
_taskQueue.Clear(); | ||
_taskStatistics.Clear(); | ||
ResetTaskSource(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using HotChocolate.Fetching; | ||
using HotChocolate.Execution.Utilities; | ||
using Microsoft.Extensions.ObjectPool; | ||
using System; | ||
|
||
namespace HotChocolate.Execution | ||
{ | ||
internal partial class ExecutionContext : IExecutionContext | ||
{ | ||
private readonly TaskQueue _taskQueue; | ||
private readonly TaskStatistics _taskStatistics; | ||
private readonly object _engineLock = new object(); | ||
private TaskCompletionSource<bool>? _waitForEngineTask; | ||
|
||
public ExecutionContext( | ||
ObjectPool<ResolverTask> taskPool, | ||
IBatchDispatcher batchDispatcher) | ||
{ | ||
_taskStatistics = new TaskStatistics(); | ||
_taskQueue = new TaskQueue(_taskStatistics, taskPool); | ||
TaskPool = taskPool; | ||
BatchDispatcher = batchDispatcher; | ||
BatchDispatcher.TaskEnqueued += BatchDispatcherEventHandler; | ||
TaskStats.StateChanged += TaskStatisticsEventHandler; | ||
} | ||
|
||
public ITaskQueue Tasks => _taskQueue; | ||
|
||
public ITaskStatistics TaskStats => _taskStatistics; | ||
|
||
public bool IsCompleted => TaskStats.Enqueued == 0 && TaskStats.Running == 0; | ||
|
||
public ObjectPool<ResolverTask> TaskPool { get; } | ||
|
||
public IBatchDispatcher BatchDispatcher { get; } | ||
|
||
public Task WaitForEngine(CancellationToken cancellationToken) | ||
{ | ||
TaskCompletionSource<bool>? waitForEngineTask = _waitForEngineTask; | ||
if (waitForEngineTask == null) | ||
{ | ||
return Task.CompletedTask; | ||
} | ||
|
||
cancellationToken.Register(() => waitForEngineTask.SetCanceled()); | ||
return waitForEngineTask.Task; | ||
} | ||
|
||
private void SetEngineState() | ||
{ | ||
lock (_engineLock) | ||
{ | ||
if (TaskStats.Enqueued > 0 || BatchDispatcher.HasTasks || IsCompleted) | ||
{ | ||
// in case there is a task someone might be already waiting, | ||
// in this case we have to complete the task and clear it | ||
if (_waitForEngineTask != null) | ||
{ | ||
ResetTaskSource(); | ||
} | ||
} | ||
else | ||
{ | ||
// in case there is a task someone might be already waiting, | ||
// if there is no task we have to create one | ||
if (_waitForEngineTask == null) | ||
{ | ||
_waitForEngineTask = new TaskCompletionSource<bool>(); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private void BatchDispatcherEventHandler(object? source, EventArgs args) => | ||
SetEngineState(); | ||
|
||
private void TaskStatisticsEventHandler(object? source, EventArgs args) => | ||
SetEngineState(); | ||
|
||
private void ResetTaskSource() | ||
{ | ||
_waitForEngineTask?.SetResult(true); | ||
_waitForEngineTask = null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
using System; | ||
using System.Threading; | ||
|
||
namespace HotChocolate.Execution | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
using System; | ||
using System.Threading; | ||
|
||
namespace HotChocolate.Execution | ||
{ | ||
internal class TaskStatistics : ITaskStatistics | ||
{ | ||
private int _running; | ||
private int _enqueued; | ||
|
||
public event EventHandler<EventArgs>? StateChanged; | ||
|
||
public int Enqueued => _enqueued; | ||
|
||
public int Running => _running; | ||
|
||
public void TaskEnqueued() | ||
{ | ||
Interlocked.Increment(ref _enqueued); | ||
StateChanged?.Invoke(this, EventArgs.Empty); | ||
} | ||
|
||
public void TaskDequeued() | ||
{ | ||
Interlocked.Decrement(ref _enqueued); | ||
StateChanged?.Invoke(this, EventArgs.Empty); | ||
} | ||
|
||
public void TaskStarted() | ||
{ | ||
Interlocked.Increment(ref _running); | ||
StateChanged?.Invoke(this, EventArgs.Empty); | ||
} | ||
|
||
public void TaskCompleted() | ||
{ | ||
Interlocked.Decrement(ref _running); | ||
StateChanged?.Invoke(this, EventArgs.Empty); | ||
} | ||
|
||
public void Clear() | ||
{ | ||
_running = 0; | ||
_enqueued = 0; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.