static async Task Main() { Console.Title = "Sender"; #region route-message-to-original-destination var config = new EndpointConfiguration("Sender"); var transport = config.UseTransport <LearningTransport>(); var routing = transport.Routing(); routing.RouteToEndpoint(typeof(ImportantMessage), "OriginalDestination"); #endregion var endpoint = await Endpoint.Start(config) .ConfigureAwait(false); Console.WriteLine("Endpoint Started. Press s to send a very important message. Any other key to exit"); var i = 0; while (Console.ReadKey(true).Key == ConsoleKey.S) { var message = new ImportantMessage { Text = $"Hello there: {i++}" }; await endpoint.Send(message) .ConfigureAwait(false); } await endpoint.Stop() .ConfigureAwait(false); }
public async Task Duplex_ManyParallelRequests_MessageRoundTripped() { const string ImportantMessage = @" _____ _____ _____ | __ \| __ \ / ____| __ _| |__) | |__) | | / _` | _ /| ___/| | | (_| | | \ \| | | |____ \__, |_| \_\_| \_____| __/ | |___/ _ (_) _ ___ | / __| | \__ \ _ |_|___/ | | ___ ___ ___ | | / __/ _ \ / _ \| | | (_| (_) | (_) | | \___\___/ \___/|_| "; var attempts = 100; var allUploads = new List <string>(); var allCompletedTasks = new List <Task>(); var tcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously); async Task MessageUpload( IAsyncStreamReader <StringValue> requestStream, IServerStreamWriter <StringValue> responseStream, ServerCallContext context) { // Receive chunks var chunks = new List <string>(); await foreach (var chunk in requestStream.ReadAllAsync()) { chunks.Add(chunk.Value); } Task completeTask; lock (allUploads) { allUploads.Add(string.Join(Environment.NewLine, chunks)); if (allUploads.Count < attempts) { // Check that unused calls are canceled. completeTask = Task.Run(async() => { await tcs.Task; var cancellationTcs = new TaskCompletionSource <bool>(); context.CancellationToken.Register(s => ((TaskCompletionSource <bool>)s !).SetResult(true), cancellationTcs); await cancellationTcs.Task; }); } else { // Write response in used call. completeTask = Task.Run(async() => { // Write chunks foreach (var chunk in chunks) { await responseStream.WriteAsync(new StringValue { Value = chunk }); } }); } } await completeTask; } var method = Fixture.DynamicGrpc.AddDuplexStreamingMethod <StringValue, StringValue>(MessageUpload); var channel = CreateChannel(serviceConfig: ServiceConfigHelpers.CreateHedgingServiceConfig(maxAttempts: 100, hedgingDelay: TimeSpan.Zero), maxRetryAttempts: 100); var client = TestClientFactory.Create(channel, method); using var call = client.DuplexStreamingCall(); var lines = ImportantMessage.Split(Environment.NewLine); for (var i = 0; i < lines.Length; i++) { await call.RequestStream.WriteAsync(new StringValue { Value = lines[i] }).DefaultTimeout(); await Task.Delay(TimeSpan.FromSeconds(0.01)).DefaultTimeout(); } await call.RequestStream.CompleteAsync().DefaultTimeout(); await TestHelpers.AssertIsTrueRetryAsync(() => allUploads.Count == 100, "Wait for all calls to reach server.").DefaultTimeout(); tcs.SetResult(null); var receivedLines = new List <string>(); await foreach (var line in call.ResponseStream.ReadAllAsync().DefaultTimeout()) { receivedLines.Add(line.Value); } Assert.AreEqual(ImportantMessage, string.Join(Environment.NewLine, receivedLines)); foreach (var upload in allUploads) { Assert.AreEqual(ImportantMessage, upload); } await Task.WhenAll(allCompletedTasks).DefaultTimeout(); }