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(); } }
private async Task RunTestCase(Func <AbsolutePath, IContentSession, GrpcCopyClient, Task> testAct, [CallerMemberName] string testName = null) { var cacheName = testName + "_cache"; testName += Guid.NewGuid(); // Using a guid to disambiguate scenario name. 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, 42, ServiceConfiguration.DefaultGracefulShutdownSeconds, grpcPort, grpcPortFileName) { CopyRequestHandlingCountLimit = _copyToLimit, ProactivePushCountLimit = _proactivePushCountLimit }; var storeConfig = ContentStoreConfiguration.CreateWithMaxSizeQuotaMB(1); Func <AbsolutePath, IContentStore> contentStoreFactory = (path) => new FileSystemContentStore( FileSystem, SystemClock.Instance, directory.Path, new ConfigurationModel(storeConfig)); var server = new LocalContentServer(FileSystem, Logger, testName, contentStoreFactory, new LocalServerConfiguration(configuration)); await server.StartupAsync(_context).ShouldBeSuccess(); var sessionData = new LocalContentServerSessionData(testName, Capabilities.ContentOnly, ImplicitPin.PutAndGet, pins: null); var createSessionResult = await server.CreateSessionAsync(new OperationContext(_context), sessionData, cacheName); createSessionResult.ShouldBeSuccess(); (int sessionId, _) = createSessionResult.Value; using var sessionReference = server.GetSession(sessionId); var session = sessionReference.Session; // Create a GRPC client to connect to the server var port = new MemoryMappedFilePortReader(grpcPortFileName, Logger).ReadPort(); await _clientCache.UseAsync(new OperationContext(_context), LocalHost, port, async (nestedContext, grpcCopyClient) => { await testAct(rootPath, session, grpcCopyClient); return(Unit.Void); }); await server.ShutdownAsync(_context).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(); } }
private async Task RunTestCase(string testName, Func <AbsolutePath, IContentSession, GrpcCopyClient, Task> testAct) { var cacheName = testName + "_cache"; 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, 42, ServiceConfiguration.DefaultGracefulShutdownSeconds, grpcPort, grpcPortFileName); var storeConfig = ContentStoreConfiguration.CreateWithMaxSizeQuotaMB(1); Func <AbsolutePath, IContentStore> contentStoreFactory = (path) => new FileSystemContentStore( FileSystem, SystemClock.Instance, directory.Path, new ConfigurationModel(storeConfig)); var server = new LocalContentServer(FileSystem, Logger, testName, contentStoreFactory, new LocalServerConfiguration(configuration)); await server.StartupAsync(_context).ShouldBeSuccess(); var createSessionResult = await server.CreateSessionAsync(new OperationContext(_context), testName, cacheName, ImplicitPin.PutAndGet, Capabilities.ContentOnly); createSessionResult.ShouldBeSuccess(); (int sessionId, AbsolutePath tempDir) = createSessionResult.Value; var session = server.GetSession(sessionId); // Create a GRPC client to connect to the server var port = new MemoryMappedFilePortReader(grpcPortFileName, Logger).ReadPort(); using (var clientWrapper = await _clientCache.CreateAsync(LocalHost, port, false)) { // Run validation await testAct(rootPath, session, clientWrapper.Value); } await server.ShutdownAsync(_context).ShouldBeSuccess(); } }
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(); } } }
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(); } } }