public OperationCacheMiddleware(
     RequestDelegate next,
     IDiagnosticEvents diagnosticEvents,
     IPreparedOperationCache operationCache)
 {
     _next = next ??
             throw new ArgumentNullException(nameof(next));
     _diagnosticEvents = diagnosticEvents ??
                         throw new ArgumentNullException(nameof(diagnosticEvents));
     _operationCache = operationCache ??
                       throw new ArgumentNullException(nameof(operationCache));
 }
        public async Task AutoMerge_HotReload_ClearOperationCaches()
        {
            // arrange
            using var cts = new CancellationTokenSource(20_000);
            NameString         configurationName  = "C" + Guid.NewGuid().ToString("N");
            var                schemaDefinitionV2 = FileResource.Open("AccountSchemaDefinition.json");
            IHttpClientFactory httpClientFactory  = CreateDefaultRemoteSchemas(configurationName);
            DocumentNode       document           = Utf8GraphQLParser.Parse("{ foo }");
            var                queryHash          = "abc";

            IDatabase database = _connection.GetDatabase();

            while (!cts.IsCancellationRequested)
            {
                if (await database.SetLengthAsync(configurationName.Value) == 4)
                {
                    break;
                }

                await Task.Delay(150, cts.Token);
            }

            ServiceProvider serviceProvider =
                new ServiceCollection()
                .AddSingleton(httpClientFactory)
                .AddGraphQL()
                .AddQueryType(d => d.Name("Query").Field("foo").Resolve("foo"))
                .AddRemoteSchemasFromRedis(configurationName, _ => _connection)
                .Services
                .BuildServiceProvider();

            IRequestExecutorResolver executorResolver =
                serviceProvider.GetRequiredService <IRequestExecutorResolver>();
            IDocumentCache documentCache =
                serviceProvider.GetRequiredService <IDocumentCache>();
            IPreparedOperationCache preparedOperationCache =
                serviceProvider.GetRequiredService <IPreparedOperationCache>();

            await executorResolver.GetRequestExecutorAsync(cancellationToken : cts.Token);

            var raised = false;

            executorResolver.RequestExecutorEvicted += (_, args) =>
            {
                if (args.Name.Equals(Schema.DefaultName))
                {
                    raised = true;
                }
            };

            Assert.False(documentCache.TryGetDocument(queryHash, out _));
            Assert.False(preparedOperationCache.TryGetOperation(queryHash, out _));

            IRequestExecutor requestExecutor =
                await executorResolver.GetRequestExecutorAsync(cancellationToken : cts.Token);

            await requestExecutor
            .ExecuteAsync(QueryRequestBuilder
                          .New()
                          .SetQuery(document)
                          .SetQueryHash(queryHash)
                          .Create(),
                          cts.Token);

            Assert.True(preparedOperationCache.TryGetOperation("_Default-1-abc", out _));

            // act
            await database.StringSetAsync($"{configurationName}.{_accounts}", schemaDefinitionV2);

            await _connection.GetSubscriber().PublishAsync(configurationName.Value, _accounts);

            while (!cts.IsCancellationRequested)
            {
                if (raised)
                {
                    break;
                }

                await Task.Delay(150, cts.Token);
            }

            // assert
            Assert.True(documentCache.TryGetDocument(queryHash, out _));
            Assert.False(preparedOperationCache.TryGetOperation(queryHash, out _));
        }