Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions src/HotChocolate/AspNetCore/benchmarks/k6/performance-data.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
{
"timestamp": "2025-10-23T19:09:41Z",
"timestamp": "2025-10-24T15:17:25Z",
"tests": {
"single-fetch": {
"name": "Single Fetch (50 products, names only)",
"response_time": {
"min": 1.311196,
"p50": 1.763142,
"max": 50.855832,
"avg": 1.968737330531039,
"p90": 2.5424552000000005,
"p95": 2.9549014,
"p99": 5.398412600000002
"min": 1.300229,
"p50": 1.677071,
"max": 45.722702,
"avg": 1.860241621288515,
"p90": 2.3472704,
"p95": 2.7397823999999993,
"p99": 5.095712309999996
},
"throughput": {
"requests_per_second": 78.78513545438359,
"total_iterations": 7168
"requests_per_second": 78.81265576267907,
"total_iterations": 7171
},
"reliability": {
"error_rate": 0
Expand All @@ -23,17 +23,17 @@
"dataloader": {
"name": "DataLoader (50 products with brands)",
"response_time": {
"min": 2.581101,
"p50": 3.39728,
"max": 19.088613,
"avg": 3.776861670740273,
"p90": 5.147565999999999,
"p95": 6.316323699999998,
"p99": 8.866344979999997
"min": 2.555435,
"p50": 3.141933,
"max": 14.603534,
"avg": 3.471868218227772,
"p90": 4.542777,
"p95": 5.61032,
"p99": 8.034627400000009
},
"throughput": {
"requests_per_second": 78.61021441670597,
"total_iterations": 7150
"requests_per_second": 78.59853943647569,
"total_iterations": 7152
},
"reliability": {
"error_rate": 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace HotChocolate.AspNetCore.Warmup;

internal sealed class RequestExecutorWarmupService(
IOptionsMonitor<RequestExecutorSetup> optionsMonitor,
IRequestExecutorOptionsMonitor optionsMonitor,
IRequestExecutorProvider provider) : IHostedService
{
public async Task StartAsync(CancellationToken cancellationToken)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Microsoft.Extensions.Options;

namespace HotChocolate.Execution.Configuration;

internal sealed class DefaultRequestExecutorOptionsMonitor(
IOptionsMonitor<RequestExecutorSetup> optionsMonitor)
: IRequestExecutorOptionsMonitor
{
public RequestExecutorSetup Get(string schemaName) => optionsMonitor.Get(schemaName);

public IDisposable? OnChange(Action<string> listener)
=> optionsMonitor.OnChange((_, schemaName) => listener(schemaName!));
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace HotChocolate.Execution.Configuration;

/// <summary>
/// Used for notifications when <see cref="RequestExecutorSetup"/> instances change.
/// </summary>
public interface IRequestExecutorOptionsMonitor
{
/// <summary>
/// Returns a configured <see cref="RequestExecutorSetup"/>
/// instance with the given name.
/// </summary>
RequestExecutorSetup Get(string schemaName);

/// <summary>
/// Registers a listener to be called whenever a named
/// <see cref="RequestExecutorSetup"/> changes.
/// </summary>
/// <param name="listener">
/// The action to be invoked when <see cref="RequestExecutorSetup"/> has changed.
/// </param>
/// <returns>
/// An <see cref="IDisposable"/> which should be disposed to stop listening for changes.
/// </returns>
IDisposable? OnChange(Action<string> listener);
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
using GreenDonut;
using GreenDonut.DependencyInjection;
using HotChocolate.Execution;
using HotChocolate.Execution.Configuration;
using HotChocolate.Execution.DependencyInjection;
using HotChocolate.Execution.Options;
using HotChocolate.Execution.Processing;
using HotChocolate.Execution.Processing.Tasks;
using HotChocolate.Fetching;
using HotChocolate.Internal;
using HotChocolate.Language;
using HotChocolate.Types;
using HotChocolate.Utilities;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options;

// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection;

internal static class InternalServiceCollectionExtensions
{
internal static IServiceCollection TryAddRequestExecutorOptionsMonitor(
this IServiceCollection services)
{
services.TryAddSingleton<IRequestExecutorOptionsMonitor>(
sp => new DefaultRequestExecutorOptionsMonitor(
sp.GetRequiredService<IOptionsMonitor<RequestExecutorSetup>>()));
return services;
}

internal static IServiceCollection TryAddVariableCoercion(
this IServiceCollection services)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using HotChocolate.Execution.Configuration;
using HotChocolate.Language;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;

namespace Microsoft.Extensions.DependencyInjection;

Expand All @@ -15,7 +14,7 @@ internal static IRequestExecutorBuilder AddDocumentCache(this IRequestExecutorBu
builder.Name,
static (sp, schemaName) =>
{
var optionsMonitor = sp.GetRequiredService<IOptionsMonitor<RequestExecutorSetup>>();
var optionsMonitor = sp.GetRequiredService<IRequestExecutorOptionsMonitor>();
var setup = optionsMonitor.Get((string)schemaName!);
var options = setup.CreateSchemaOptions();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public static IServiceCollection AddGraphQLCore(this IServiceCollection services

// core services
services
.TryAddRequestExecutorOptionsMonitor()
.TryAddTypeConverter()
.TryAddInputFormatter()
.TryAddInputParser()
Expand Down
7 changes: 4 additions & 3 deletions src/HotChocolate/Core/src/Execution/RequestExecutorManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options;
using static HotChocolate.Execution.ThrowHelper;

namespace HotChocolate.Execution;
Expand All @@ -31,15 +30,15 @@ internal sealed partial class RequestExecutorManager
private readonly CancellationTokenSource _cts = new();
private readonly ConcurrentDictionary<string, SemaphoreSlim> _semaphoreBySchema = new();
private readonly ConcurrentDictionary<string, RegisteredExecutor> _executors = new();
private readonly IOptionsMonitor<RequestExecutorSetup> _optionsMonitor;
private readonly IRequestExecutorOptionsMonitor _optionsMonitor;
private readonly IServiceProvider _applicationServices;
private readonly EventObservable _events = new();
private readonly ChannelWriter<string> _executorEvictionChannelWriter;
private ulong _version;
private bool _disposed;

public RequestExecutorManager(
IOptionsMonitor<RequestExecutorSetup> optionsMonitor,
IRequestExecutorOptionsMonitor optionsMonitor,
IServiceProvider serviceProvider)
{
ArgumentNullException.ThrowIfNull(optionsMonitor);
Expand All @@ -53,6 +52,8 @@ public RequestExecutorManager(

ConsumeExecutorEvictionsAsync(executorEvictionChannel.Reader, _cts.Token).FireAndForget();

_optionsMonitor.OnChange(EvictExecutor);

var schemaNames = _applicationServices.GetService<IEnumerable<SchemaName>>()?
.Select(x => x.Value).Distinct().Order().ToImmutableArray();
SchemaNames = schemaNames ?? [];
Expand Down
Loading