private static void ProcessValue(RedisPipelineItem redisItem, byte[] value) { if (value == null) { redisItem.OnSuccess(null); return; } var result = new byte[1][]; result[0] = value; redisItem.OnSuccess(result); }
public Task <byte[]> SendCommandAsync(params byte[][] requestData) { var taskCompletion = new TaskCompletionSource <byte[]>(); var request = new RedisPipelineItem( requestData, taskCompletion.SetException, result => taskCompletion.SetResult(result.CollapseArray())); RequestQueue.Enqueue(request); _diagnosticSource.LogEvent("RequestEnqueue", request); return(EnsureSendCommandAsync(taskCompletion)); }
private async Task SendAsync() { _diagnosticSource.LogEvent("SendStart"); RedisPipelineItem currentItem = null; try { await _redisWriter.CreateNewBufferAsync().ConfigureAwait(false); while (RequestQueue.TryDequeue(out currentItem)) { _diagnosticSource.LogEvent("WriteItemStart", currentItem); await _redisWriter.WriteRedisRequestAsync(currentItem.Data).ConfigureAwait(false); _diagnosticSource.LogEvent("WriteItemStop", currentItem); _responseQueue.Enqueue(currentItem); FireAndForget(StartReceiveIfNotRunning()); if (_redisWriter.BufferCount <= 1) { continue; } _diagnosticSource.LogEvent("FlushWriteBufferStart"); await _redisWriter.FlushWriteBufferAsync().ConfigureAwait(false); _diagnosticSource.LogEvent("FlushWriteBufferStop"); break; } _diagnosticSource.LogEvent("FlushWriteBufferStart"); await _redisWriter.FlushWriteBufferAsync().ConfigureAwait(false); _diagnosticSource.LogEvent("FlushWriteBufferStop"); } catch (Exception error) { _pipelineException = error; ThrowErrorForRemainingResponseQueueItems(); currentItem?.OnError(error); _diagnosticSource.LogEvent("SendException", error); } finally { _redisWriter.CheckInBuffers(); } _diagnosticSource.LogEvent("SendStop"); }
private async Task ReceiveAsync() { _diagnosticSource.LogEvent("ReceiveStart"); if (_pipelineException != null) { ThrowErrorForRemainingResponseQueueItems(); return; } RedisPipelineItem currentItem = null; try { while (_responseQueue.TryDequeue(out currentItem)) { _diagnosticSource.LogEvent("ReceiveItemStart", currentItem); await _redisReader.ReadAsync(currentItem).ConfigureAwait(false); _diagnosticSource.LogEvent("ReceiveItemStop", currentItem); } } catch (Exception error) { _pipelineException = error; ThrowErrorForRemainingResponseQueueItems(); currentItem?.OnError(error); _diagnosticSource.LogEvent("ReceiveException", error); } finally { _redisReader.CheckInBuffers(); } _diagnosticSource.LogEvent("ReceiveStop"); _lastCommandTicks = Environment.TickCount; }
public async Task ReadAsync(RedisPipelineItem redisItem) { // Everything is inline to prevent unncessary task allocations // this code is called A LOT await ReadResponseAsync().ConfigureAwait(false); if (CurrentPosition >= CurrentResponse.Count) { await ReadNextResponseAsync().ConfigureAwait(false); } var firstChar = ReadFirstChar(); if (firstChar == RedisProtocolContants.SimpleString) { if (CurrentPosition >= CurrentResponse.Count) { await ReadNextResponseAsync().ConfigureAwait(false); } var bytes = new List <byte>(); var response = (IList <byte>)CurrentResponse; var currentChar = response[CurrentPosition]; while (currentChar != RedisProtocolContants.LineFeed) { if (currentChar != RedisProtocolContants.CarriageReturn) { bytes.Add(currentChar); } CurrentPosition++; if (CurrentPosition >= CurrentResponse.Count) { await ReadNextResponseAsync().ConfigureAwait(false); response = CurrentResponse; } currentChar = response[CurrentPosition]; } CurrentPosition++; ProcessValue(redisItem, bytes.ToArray()); } else if (firstChar == RedisProtocolContants.Integer) { if (CurrentPosition >= CurrentResponse.Count) { await ReadNextResponseAsync().ConfigureAwait(false); } var bytes = new List <byte>(); var response = (IList <byte>)CurrentResponse; var currentChar = response[CurrentPosition]; while (currentChar != RedisProtocolContants.LineFeed) { if (currentChar != RedisProtocolContants.CarriageReturn) { bytes.Add(currentChar); } CurrentPosition++; if (CurrentPosition >= CurrentResponse.Count) { await ReadNextResponseAsync().ConfigureAwait(false); response = CurrentResponse; } currentChar = response[CurrentPosition]; } CurrentPosition++; ProcessValue(redisItem, bytes.ToArray()); } else if (firstChar == RedisProtocolContants.BulkString) { var length = await ReadLengthAsync().ConfigureAwait(false); if (length == -1) { ProcessValue(redisItem, null); return; } var bytes = new List <byte>(); var response = (IList <byte>)CurrentResponse; for (var i = 0; i < length; i++) { if (CurrentPosition >= CurrentResponse.Count) { await ReadNextResponseAsync().ConfigureAwait(false); response = CurrentResponse; } var currentChar = response[CurrentPosition]; bytes.Add(currentChar); CurrentPosition++; } for (var i = 0; i < 2; i++) { if (CurrentPosition >= CurrentResponse.Count) { await ReadNextResponseAsync().ConfigureAwait(false); } CurrentPosition++; } ProcessValue(redisItem, bytes?.ToArray()); } else if (firstChar == RedisProtocolContants.Array) { var value = await ReadArrayAsync().ConfigureAwait(false); redisItem.OnSuccess(value); } else if (firstChar == RedisProtocolContants.Error) { if (CurrentPosition >= CurrentResponse.Count) { await ReadNextResponseAsync().ConfigureAwait(false); } var bytes = new List <byte>(); var response = (IList <byte>)CurrentResponse; var currentChar = response[CurrentPosition]; while (currentChar != RedisProtocolContants.LineFeed) { if (currentChar != RedisProtocolContants.CarriageReturn) { bytes.Add(currentChar); } CurrentPosition++; if (CurrentPosition >= CurrentResponse.Count) { await ReadNextResponseAsync().ConfigureAwait(false); response = CurrentResponse; } currentChar = response[CurrentPosition]; } CurrentPosition++; var errorText = Encoding.UTF8.GetString(bytes.ToArray()); var exception = new RedisException(errorText); redisItem.OnError(exception); } else { var exception = new RedisException("Could not process Redis response."); throw exception; // restart the pipeline. } }