internal async Task CallAsync(RespConnection connection, List <IBatchedOperation> operations, CancellationToken cancellationToken) { try { int len = operations.Count; if (len == 0) { return; } // push the fisrt *before* we context-switch; the rest can wait await SendAsync(this, connection, operations[0], cancellationToken, true).ConfigureAwait(false); Task?bgSend = len == 1 ? null : BeginSendRemainderInBackground(this, connection, operations, default); foreach (var op in operations) // then receive all { using var response = await connection.ReceiveAsync().ConfigureAwait(false); try { response.Value.ThrowIfError(); op.ProcessResponse(response.Value); } catch (Exception ex) { op.TrySetException(ex); } } if (bgSend != null) { Wait(bgSend); } } catch (Exception ex) { connection.Doom(); foreach (var op in operations) // fault anything that is left after a global explosion { op.TrySetException(ex); } } }
static async Task RunClientAsync(RespConnection client, int pingsPerClient, int pipelineDepth, string payload) { var frame = string.IsNullOrEmpty(payload) ? s_ping : RespValue.CreateAggregate(RespType.Array, "PING", payload); var expected = string.IsNullOrEmpty(payload) ? s_pong : RespValue.Create(RespType.BlobString, payload); if (pipelineDepth == 1) { for (int i = 0; i < pingsPerClient; i++) { await client.SendAsync(frame).ConfigureAwait(false); using var result = await client.ReceiveAsync().ConfigureAwait(false); result.Value.ThrowIfError(); if (!result.Value.Equals(expected)) { Throw(); } // await client.PingAsync(); } } else { using var frames = Replicate(frame, pipelineDepth); for (int i = 0; i < pingsPerClient; i++) { using var batch = await client.BatchAsync(frames.Value).ConfigureAwait(false); CheckBatchForErrors(batch.Value, expected); } } }