private async Task LongCallCanceledOnShutdownAsync <T>(
            string scenario, bool respectsCancellationToken, Func <OperationContext, AbsolutePath, IRpcClient, Task <T> > unresponsiveFunc)
        {
            var tracingContext = new Context(Logger);
            var context        = new OperationContext(tracingContext);

            using (var directory = new DisposableDirectory(FileSystem))
            {
                var rootPath = directory.Path;

                var namedCacheRoots = new Dictionary <string, AbsolutePath> {
                    { CacheName, rootPath }
                };
                var grpcPort         = PortExtensions.GetNextAvailablePort();
                var grpcPortFileName = Guid.NewGuid().ToString();
                var configuration    = new ServiceConfiguration(
                    namedCacheRoots,
                    rootPath,
                    MaxConnections,
                    ServiceConfiguration.DefaultGracefulShutdownSeconds,
                    grpcPort,
                    grpcPortFileName);

                // Use a store which gets stuck forever on the session operations (pin/place/put/open) unless canceled,
                // and configurably ignoring the cancellation token to simulate long operations that might not check
                // the token quickly enough.
                var unresponsivenessHasStartedSemaphore = new SemaphoreSlim(0, 1);
                Func <AbsolutePath, IContentStore> contentStoreFactory =
                    path => new TestHangingContentStore(respectsCancellationToken, unresponsivenessHasStartedSemaphore);

                IRpcClient rpcClient;
                Task <T>   unresponsiveTask;
                using (var server = new LocalContentServer(FileSystem, Logger, scenario, contentStoreFactory, new LocalServerConfiguration(configuration)))
                {
                    var tracer = new ServiceClientContentSessionTracer("TestTracerForRpcClient");
                    await server.StartupAsync(context).ShouldBeSuccess();

                    var port = new MemoryMappedFilePortReader(grpcPortFileName, Logger).ReadPort();
                    rpcClient = new GrpcContentClient(tracer, FileSystem, new ServiceClientRpcConfiguration(grpcPort), scenario);

                    await rpcClient.CreateSessionAsync(
                        context, SessionName, CacheName, ImplicitPin.None).ShouldBeSuccess();

                    // Start the task which we expect to become unresponsive
                    unresponsiveTask = unresponsiveFunc(context, directory.CreateRandomFileName(), rpcClient);

                    // Synchronize with the store's unresponsiveness.
                    await unresponsivenessHasStartedSemaphore.WaitAsync();

                    await server.ShutdownAsync(context).ShouldBeSuccess();
                }

                // Make sure that the client gets a retryable exception
                Func <Task> awaitUnresponsiveTaskFunc = async() => await unresponsiveTask;
                awaitUnresponsiveTaskFunc.Should().Throw <ClientCanRetryException>();

                (await rpcClient.ShutdownAsync(context)).ShouldBeSuccess();
                rpcClient.Dispose();
            }
        }
Example #2
0
        private async Task RunServerTestAsync(Context context, string scenario, Func <Context, ServiceConfiguration, IRpcClient, Task> funcAsync)
        {
            using (var directory = new DisposableDirectory(FileSystem))
            {
                var storeConfig = new ContentStoreConfiguration(new MaxSizeQuota($"{1 * 1024 * 1024}"));
                await storeConfig.Write(FileSystem, directory.Path).ConfigureAwait(false);

                var serviceConfig =
                    new ServiceConfiguration(
                        new Dictionary <string, AbsolutePath> {
                    { CacheName, directory.Path }
                },
                        directory.Path,
                        ServiceConfiguration.DefaultMaxConnections,
                        ServiceConfiguration.DefaultGracefulShutdownSeconds,
                        PortExtensions.GetNextAvailablePort(),
                        Guid.NewGuid().ToString())
                {
                    TraceGrpcOperation = true
                };

                using (var server = new LocalContentServer(FileSystem, Logger, scenario, path => new FileSystemContentStore(FileSystem, SystemClock.Instance, path), new LocalServerConfiguration(serviceConfig)))
                {
                    BoolResult r = await server.StartupAsync(context).ConfigureAwait(false);

                    r.ShouldBeSuccess();
                    var configuration = new ServiceClientRpcConfiguration()
                    {
                        GrpcPort = (int)serviceConfig.GrpcPort,
                    };

                    using (var rpcClient = new GrpcContentClient(new ServiceClientContentSessionTracer(scenario), FileSystem, configuration, scenario))
                    {
                        try
                        {
                            var createSessionResult = await rpcClient.CreateSessionAsync(new OperationContext(context), SessionName, CacheName, ImplicitPin.None);

                            createSessionResult.ShouldBeSuccess();

                            await funcAsync(context, serviceConfig, rpcClient);
                        }
                        finally
                        {
                            (await rpcClient.ShutdownAsync(context)).ShouldBeSuccess();
                        }
                    }

                    r = await server.ShutdownAsync(context);

                    r.ShouldBeSuccess();
                }
            }
        }
        public async Task CreateSessionThrowsClientCanRetryExceptionWhenServiceOffline()
        {
            string scenario       = nameof(CreateSessionThrowsClientCanRetryExceptionWhenServiceOffline);
            var    tracingContext = new Context(Logger);
            var    context        = new OperationContext(tracingContext);

            using (var directory = new DisposableDirectory(FileSystem))
            {
                var rootPath = directory.Path;

                var namedCacheRoots = new Dictionary <string, AbsolutePath> {
                    { CacheName, rootPath }
                };
                var grpcPort         = PortExtensions.GetNextAvailablePort();
                var grpcPortFileName = Guid.NewGuid().ToString();
                var configuration    = new ServiceConfiguration(
                    namedCacheRoots,
                    rootPath,
                    MaxConnections,
                    ServiceConfiguration.DefaultGracefulShutdownSeconds,
                    grpcPort,
                    grpcPortFileName);
                Func <AbsolutePath, IContentStore> contentStoreFactory =
                    path =>
                    new FileSystemContentStore(
                        FileSystem,
                        SystemClock.Instance,
                        rootPath,
                        new ConfigurationModel(new ContentStoreConfiguration(new MaxSizeQuota("1KB"))));

                IRpcClient rpcClient;
                using (var server = new LocalContentServer(FileSystem, Logger, scenario, contentStoreFactory, new LocalServerConfiguration(configuration)))
                {
                    var        tracer = new ServiceClientContentSessionTracer("TestTracerForRpcClient");
                    BoolResult r      = await server.StartupAsync(context).ConfigureAwait(false);

                    r.ShouldBeSuccess();

                    var port = new MemoryMappedFilePortReader(grpcPortFileName, Logger).ReadPort();
                    rpcClient = new GrpcContentClient(tracer, FileSystem, new ServiceClientRpcConfiguration(grpcPort), scenario);

                    r = await server.ShutdownAsync(context);

                    r.ShouldBeSuccess();
                }

                Func <Task <BoolResult> > createSessionFunc = () => rpcClient.CreateSessionAsync(context, SessionName, CacheName, ImplicitPin.None);
                createSessionFunc.Should().Throw <ClientCanRetryException>();

                rpcClient.Dispose();
            }
        }
        public async Task PutStreamRetriesWhenTempFileDisappears()
        {
            string scenario       = nameof(PutStreamRetriesWhenTempFileDisappears);
            var    tracingContext = new Context(Logger);
            var    context        = new OperationContext(tracingContext);

            using (var directory = new DisposableDirectory(FileSystem))
            {
                var rootPath = directory.Path;

                var namedCacheRoots = new Dictionary <string, AbsolutePath> {
                    { CacheName, rootPath }
                };
                var grpcPort         = PortExtensions.GetNextAvailablePort();
                var grpcPortFileName = Guid.NewGuid().ToString();
                var configuration    = new ServiceConfiguration(
                    namedCacheRoots,
                    rootPath,
                    MaxConnections,
                    ServiceConfiguration.DefaultGracefulShutdownSeconds,
                    grpcPort,
                    grpcPortFileName);
                Func <AbsolutePath, IContentStore> contentStoreFactory = path => new TestTempFileDeletingContentStore(FileSystem);

                using (var server = new LocalContentServer(FileSystem, Logger, scenario, contentStoreFactory, new LocalServerConfiguration(configuration)))
                {
                    var tracer = new ServiceClientContentSessionTracer("TestTracerForRpcClient");
                    await server.StartupAsync(context).ShouldBeSuccess();

                    var port = new MemoryMappedFilePortReader(grpcPortFileName, Logger).ReadPort();
                    using (IRpcClient rpcClient = new GrpcContentClient(tracer, FileSystem, new ServiceClientRpcConfiguration(grpcPort), scenario))
                    {
                        await rpcClient.CreateSessionAsync(
                            context, SessionName, CacheName, ImplicitPin.None).ShouldBeSuccess();

                        using (var stream = new MemoryStream())
                        {
                            Func <Task <PutResult> > putFunc = () => rpcClient.PutStreamAsync(context, HashType.Vso0, stream, createDirectory: false);
                            putFunc.Should().Throw <ClientCanRetryException>();
                        }

                        (await rpcClient.ShutdownAsync(context)).ShouldBeSuccess();
                    }

                    await server.ShutdownAsync(context).ShouldBeSuccess();
                }
            }
        }
Example #5
0
        public async Task DoesNotRespectFileReplacementMode(FileReplacementMode requestedReplacementMode)
        {
            string scenario = nameof(DoesNotRespectFileReplacementMode) + requestedReplacementMode;
            var    context  = new Context(Logger);

            using (var directory = new DisposableDirectory(FileSystem))
            {
                var rootPath = directory.Path;

                var namedCacheRoots = new Dictionary <string, AbsolutePath> {
                    { CacheName, rootPath }
                };
                var grpcPort         = PortExtensions.GetNextAvailablePort();
                var grpcPortFileName = Guid.NewGuid().ToString();
                var configuration    = new ServiceConfiguration(
                    namedCacheRoots,
                    rootPath,
                    MaxConnections,
                    ServiceConfiguration.DefaultGracefulShutdownSeconds,
                    grpcPort,
                    grpcPortFileName);
                Func <AbsolutePath, IContentStore> contentStoreFactory =
                    path =>
                    new FileSystemContentStore(
                        FileSystem,
                        SystemClock.Instance,
                        rootPath,
                        new ConfigurationModel(new ContentStoreConfiguration(new MaxSizeQuota("1MB"))));

                using (var server = new LocalContentServer(FileSystem, Logger, scenario, contentStoreFactory, new LocalServerConfiguration(configuration)))
                {
                    var tracer = new ServiceClientContentSessionTracer("TestTracerForRpcClient");
                    await server.StartupAsync(context).ShouldBeSuccess();

                    var        port      = new MemoryMappedFilePortReader(grpcPortFileName, Logger).ReadPort();
                    IRpcClient rpcClient = new GrpcContentClient(tracer, FileSystem, port, scenario);

                    await rpcClient.CreateSessionAsync(
                        context, SessionName, CacheName, ImplicitPin.None).ShouldBeSuccess();

                    ContentHash contentHash;
                    using (var stream = new MemoryStream())
                    {
                        PutResult putResult = await rpcClient.PutStreamAsync(context, HashType.Vso0, stream, createDirectory : false);

                        putResult.ShouldBeSuccess();
                        putResult.ContentSize.Should().Be(0);
                        contentHash = putResult.ContentHash;
                    }

                    var tempPath = directory.CreateRandomFileName();
                    FileSystem.WriteAllBytes(tempPath, new byte[] {});

                    var placeResult = await rpcClient.PlaceFileAsync(
                        context, contentHash, tempPath, FileAccessMode.ReadOnly, requestedReplacementMode, FileRealizationMode.Any);

                    placeResult.Succeeded.Should().BeTrue();

                    (await rpcClient.ShutdownAsync(context)).ShouldBeSuccess();
                    rpcClient.Dispose();

                    await server.ShutdownAsync(context).ShouldBeSuccess();
                }
            }
        }