16
16
using HotChocolate . Types . Descriptors ;
17
17
using HotChocolate . Types . Descriptors . Definitions ;
18
18
using HotChocolate . Utilities ;
19
+ using Microsoft . Extensions . DependencyInjection . Extensions ;
20
+ using Microsoft . Extensions . ObjectPool ;
19
21
using static HotChocolate . Execution . ThrowHelper ;
20
22
21
23
namespace HotChocolate . Execution
22
24
{
23
25
internal sealed class RequestExecutorResolver
24
26
: IRequestExecutorResolver
25
- , IInternalRequestExecutorResolver
26
- , IDisposable
27
+ , IInternalRequestExecutorResolver
28
+ , IDisposable
27
29
{
28
30
private readonly SemaphoreSlim _semaphore = new ( 1 , 1 ) ;
29
31
private readonly ConcurrentDictionary < string , RegisteredExecutor > _executors = new ( ) ;
@@ -39,9 +41,9 @@ public RequestExecutorResolver(
39
41
IServiceProvider serviceProvider )
40
42
{
41
43
_optionsMonitor = optionsMonitor ??
42
- throw new ArgumentNullException ( nameof ( optionsMonitor ) ) ;
44
+ throw new ArgumentNullException ( nameof ( optionsMonitor ) ) ;
43
45
_applicationServices = serviceProvider ??
44
- throw new ArgumentNullException ( nameof ( serviceProvider ) ) ;
46
+ throw new ArgumentNullException ( nameof ( serviceProvider ) ) ;
45
47
_optionsMonitor . OnChange ( EvictRequestExecutor ) ;
46
48
}
47
49
@@ -145,8 +147,8 @@ private void BeginRunEvictionEvents(RegisteredExecutor registeredExecutor)
145
147
if ( action . AsyncAction is { } task )
146
148
{
147
149
await task . Invoke (
148
- registeredExecutor . Executor ,
149
- CancellationToken . None )
150
+ registeredExecutor . Executor ,
151
+ CancellationToken . None )
150
152
. ConfigureAwait ( false ) ;
151
153
}
152
154
}
@@ -241,18 +243,30 @@ await CreateExecutorOptionsAsync(options, cancellationToken)
241
243
_applicationServices . GetRequiredService < ITypeConverter > ( ) ,
242
244
_applicationServices . GetRequiredService < InputFormatter > ( ) ) ) ;
243
245
246
+ serviceCollection . TryAddSingleton < ObjectPoolProvider , DefaultObjectPoolProvider > ( ) ;
247
+
248
+ serviceCollection . TryAddSingleton < ObjectPool < RequestContext > > ( sp =>
249
+ {
250
+ ObjectPoolProvider provider = sp . GetRequiredService < ObjectPoolProvider > ( ) ;
251
+ var policy = new RequestContextPooledObjectPolicy (
252
+ sp . GetRequiredService < ISchema > ( ) ,
253
+ sp . GetRequiredService < IErrorHandler > ( ) ,
254
+ _applicationServices . GetRequiredService < ITypeConverter > ( ) ,
255
+ sp . GetRequiredService < IActivator > ( ) ,
256
+ sp . GetRequiredService < IDiagnosticEvents > ( ) ,
257
+ version ) ;
258
+ return provider . Create ( policy ) ;
259
+ } ) ;
260
+
244
261
serviceCollection . AddSingleton < IRequestExecutor > (
245
262
sp => new RequestExecutor (
246
263
sp . GetRequiredService < ISchema > ( ) ,
247
264
_applicationServices . GetRequiredService < DefaultRequestContextAccessor > ( ) ,
248
265
_applicationServices ,
249
266
sp ,
250
- sp . GetRequiredService < IErrorHandler > ( ) ,
251
- _applicationServices . GetRequiredService < ITypeConverter > ( ) ,
252
- sp . GetRequiredService < IActivator > ( ) ,
253
- sp . GetRequiredService < IDiagnosticEvents > ( ) ,
254
267
sp . GetRequiredService < RequestDelegate > ( ) ,
255
268
sp . GetRequiredService < BatchExecutor > ( ) ,
269
+ sp . GetRequiredService < ObjectPool < RequestContext > > ( ) ,
256
270
version ) ) ;
257
271
258
272
foreach ( Action < IServiceCollection > configureServices in options . SchemaServices )
@@ -265,12 +279,12 @@ await CreateExecutorOptionsAsync(options, cancellationToken)
265
279
266
280
lazy . Schema =
267
281
await CreateSchemaAsync (
268
- schemaName ,
269
- options ,
270
- executorOptions ,
271
- combinedServices ,
272
- typeModuleChangeMonitor ,
273
- cancellationToken )
282
+ schemaName ,
283
+ options ,
284
+ executorOptions ,
285
+ combinedServices ,
286
+ typeModuleChangeMonitor ,
287
+ cancellationToken )
274
288
. ConfigureAwait ( false ) ;
275
289
276
290
return schemaServices ;
@@ -342,7 +356,7 @@ private static async ValueTask<RequestExecutorOptions> CreateExecutorOptionsAsyn
342
356
CancellationToken cancellationToken )
343
357
{
344
358
RequestExecutorOptions executorOptions = options . RequestExecutorOptions ??
345
- new RequestExecutorOptions ( ) ;
359
+ new RequestExecutorOptions ( ) ;
346
360
347
361
foreach ( RequestExecutorOptionsAction action in options . RequestExecutorOptionsActions )
348
362
{
@@ -531,5 +545,51 @@ await typeModule.CreateTypesAsync(_context, cancellationToken)
531
545
}
532
546
}
533
547
}
548
+
549
+ private class RequestContextPooledObjectPolicy : PooledObjectPolicy < RequestContext >
550
+ {
551
+ private readonly ISchema _schema ;
552
+ private readonly ulong _executorVersion ;
553
+ private readonly IErrorHandler _errorHandler ;
554
+ private readonly ITypeConverter _converter ;
555
+ private readonly IActivator _activator ;
556
+ private readonly IDiagnosticEvents _diagnosticEvents ;
557
+
558
+ public RequestContextPooledObjectPolicy (
559
+ ISchema schema ,
560
+ IErrorHandler errorHandler ,
561
+ ITypeConverter converter ,
562
+ IActivator activator ,
563
+ IDiagnosticEvents diagnosticEvents ,
564
+ ulong executorVersion )
565
+ {
566
+ _schema = schema ??
567
+ throw new ArgumentNullException ( nameof ( schema ) ) ;
568
+ _errorHandler = errorHandler ??
569
+ throw new ArgumentNullException ( nameof ( errorHandler ) ) ;
570
+ _converter = converter ??
571
+ throw new ArgumentNullException ( nameof ( converter ) ) ;
572
+ _activator = activator ??
573
+ throw new ArgumentNullException ( nameof ( activator ) ) ;
574
+ _diagnosticEvents = diagnosticEvents ??
575
+ throw new ArgumentNullException ( nameof ( diagnosticEvents ) ) ;
576
+ _executorVersion = executorVersion ;
577
+ }
578
+
579
+
580
+ public override RequestContext Create ( )
581
+ => new ( _schema ,
582
+ _executorVersion ,
583
+ _errorHandler ,
584
+ _converter ,
585
+ _activator ,
586
+ _diagnosticEvents ) ;
587
+
588
+ public override bool Return ( RequestContext obj )
589
+ {
590
+ obj . Reset ( ) ;
591
+ return true ;
592
+ }
593
+ }
534
594
}
535
595
}
0 commit comments