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();
            }
        }
        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();
            }
        }
示例#3
0
 /// <nodoc />
 protected override void DisposeCore()
 {
     base.DisposeCore();
     _grpcClient?.Dispose();
 }
示例#4
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();
                }
            }
        }