private async Task <BoolResult> CheckGrpcPortIsOpen(Context context, uint grpcPort) { var client = new GrpcContentClient( new ServiceClientContentSessionTracer(nameof(CheckGrpcPortIsOpen)), FileSystem, new ServiceClientRpcConfiguration((int)grpcPort), scenario: nameof(CheckGrpcPortIsOpen)); var sw = Stopwatch.StartNew(); while (sw.ElapsedMilliseconds < ReadyWaitMs * 5) { try { var startupResult = await client.StartupAsync(context); if (startupResult.Succeeded) { return(BoolResult.Success); } } catch (ClientCanRetryException) { } // Wait a short time so we don't churn await Task.Delay(100); } return(new BoolResult($"Failed to detect active grpc client for {grpcPort}")); }
/// <inheritdoc /> protected override async Task <BoolResult> StartupCoreAsync(OperationContext context) { BoolResult result = await PreStartupAsync(context); var rpcConfiguration = Configuration.RpcConfiguration; if (result.Succeeded) { _grpcClient = new GrpcContentClient(SessionTracer, FileSystem, rpcConfiguration.GrpcPort, Configuration.Scenario, rpcConfiguration.HeartbeatInterval); result = await Configuration.RetryPolicy.ExecuteAsync(() => _grpcClient.StartupAsync(context, waitMs: 0)); if (!result) { await Configuration.RetryPolicy.ExecuteAsync(() => _grpcClient.ShutdownAsync(context)).ThrowIfFailure(); } } if (!result) { await PostShutdownAsync(context).ThrowIfFailure(); return(result); } return(result); }
internal void Delete ( [Required, Description(GrpcPortDescription)] int grpcPort, [Required, Description(HashTypeDescription)] string hashType, [Required, Description("Content hash value of referenced content to place")] string hash ) { Initialize(); var context = new Interfaces.Tracing.Context(_logger); var operationContext = new OperationContext(context); try { Validate(); var ht = GetHashTypeByNameOrDefault(hashType); var contentHash = new ContentHash(ht, HexUtilities.HexToBytes(hash)); GrpcContentClient client = new GrpcContentClient( new ServiceClientContentSessionTracer(nameof(Delete)), _fileSystem, new ServiceClientRpcConfiguration(grpcPort), _scenario); var deleteResult = client.DeleteContentAsync(operationContext, contentHash, deleteLocalOnly: false).GetAwaiter().GetResult(); _tracer.Always(context, deleteResult.ToString()); } catch (Exception e) { _tracer.Error(context, e, $"Unhandled exception in {nameof(Application)}.{nameof(Delete)}"); } }
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 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(); } } }
/// <inheritdoc /> public async Task <DeleteResult> DeleteFileAsync(OperationContext context, ContentHash hash, MachineLocation targetMachine) { (string host, int port) = ExtractHostInfo(targetMachine); using (var client = new GrpcContentClient( new ServiceClientContentSessionTracer(nameof(ServiceClientContentSessionTracer)), new PassThroughFileSystem(), new ServiceClientRpcConfiguration(port) { GrpcHost = host }, scenario: string.Empty)) { return(await client.DeleteContentAsync(context, hash, deleteLocalOnly : true)); } }
/// <inheritdoc /> public async Task <DeleteResult> DeleteFileAsync(OperationContext context, ContentHash hash, MachineLocation targetMachine) { var targetPath = new AbsolutePath(targetMachine.Path); var targetMachineName = targetPath.IsLocal ? "localhost" : targetPath.GetSegments()[0]; using (var client = new GrpcContentClient( new ServiceClientContentSessionTracer(nameof(ServiceClientContentSessionTracer)), new PassThroughFileSystem(), new ServiceClientRpcConfiguration(_grpcPort) { GrpcHost = targetMachineName }, scenario: string.Empty)) { return(await client.DeleteContentAsync(context, hash, deleteLocalOnly : true)); } }
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(); } } }