protected TValue Call <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse) { _redisSocket.Write(cmd); var rt = _redisSocket.Read(false); return(parse(rt)); }
void StartRead() { new Thread(() => { var timer = new Timer(state => { try { WriteInQueue("PING"); } catch { } }, null, 10000, 10000); while (_runing) { RedisResult rt; try { rt = _rds.Read(false); } catch (Exception ioex) { ClearAndTrySetExpcetion(ioex); Interlocked.Exchange(ref _exception, ioex); continue; } if (_writeQueue.TryDequeue(out var witem)) { witem.TaskCompletionSource.TrySetResult(rt); } else { ClearAndTrySetExpcetion(new RedisClientException($"AsyncRedisSocket: Message sequence error")); } } timer.Dispose(); }).Start(); }
public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse) { TryMulti(); return(TopOwner.LogCall(cmd, () => { _redisSocket.Write(cmd); _redisSocket.Read(cmd._flagReadbytes).ThrowOrValue <TValue>(useDefaultValue: true); _commands.Add(new TransactionCommand { Command = cmd, Parse = obj => parse(new RedisResult(obj, true, RedisMessageType.SimpleString) { Encoding = _redisSocket.Encoding }) }); return default(TValue); })); }
static void EndPipe(IRedisSocket rds, IEnumerable <PipelineCommand> cmds) { var err = new List <PipelineCommand>(); var ms = new MemoryStream(); try { var respWriter = new RespHelper.Resp3Writer(ms, rds.Encoding, rds.Protocol); foreach (var cmd in cmds) { respWriter.WriteCommand(cmd.Command); } if (rds.IsConnected == false) { rds.Connect(); } ms.Position = 0; ms.CopyTo(rds.Stream); foreach (var pc in cmds) { pc.RedisResult = rds.Read(pc.IsBytes); pc.Result = pc.Parse(pc.RedisResult); if (pc.RedisResult.IsError) { err.Add(pc); } #if net40 #else pc.TrySetResult(pc.Result, pc.RedisResult.IsError ? new RedisServerException(pc.RedisResult.SimpleError) : null); #endif } } finally { ms.Close(); ms.Dispose(); } if (err.Any()) { var sb = new StringBuilder(); for (var a = 0; a < err.Count; a++) { var cmd = err[a].Command; if (a > 0) { sb.Append("\r\n"); } sb.Append(err[a].RedisResult.SimpleError).Append(" {").Append(cmd.ToString()).Append("}"); } throw new RedisServerException(sb.ToString()); } }
public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse) { return(TopOwner.LogCall(cmd, () => { _redisSocket.Write(cmd); var rt = _redisSocket.Read(cmd); if (cmd._command == "QUIT") { _redisSocket.ReleaseSocket(); } return parse(rt); })); }
public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse) { return(TopOwner.LogCall(cmd, () => { _redisSocket.Write(cmd); var rt = _redisSocket.Read(cmd._flagReadbytes); if (cmd._command == "QUIT") { _redisSocket.ReleaseSocket(); } rt.IsErrorThrow = TopOwner._isThrowRedisSimpleError; return parse(rt); })); }
WriteAsyncInfo WriteInQueue(CommandPacket cmd) { var ret = new WriteAsyncInfo { Command = cmd }; if (_rds.ClientReply == ClientReplyType.on) { ret.TaskCompletionSource = new TaskCompletionSource <RedisResult>(); } var isnew = false; lock (_writeAsyncLock) { _writeQueue.Enqueue(ret); if (_isfirst == false) { isnew = _isfirst = true; } if (_bufferStream == null) { _bufferStream = new MemoryStream(); } new RespHelper.Resp3Writer(_bufferStream, _rds.Encoding, _rds.Protocol).WriteCommand(cmd); } if (isnew) { //Thread.CurrentThread.Join(TimeSpan.FromTicks(1000)); try { if (_rds.IsConnected == false) { _rds.Connect(); } } catch (Exception ioex) { lock (_writeAsyncLock) { while (_writeQueue.TryDequeue(out var wq)) { wq.TaskCompletionSource?.TrySetException(ioex); } _bufferStream.Close(); _bufferStream.Dispose(); _bufferStream = null; } _rds.ReleaseSocket(); _end(_rds, ioex); throw ioex; } for (var a = 0; a < 100; a++) { var cou = _writeQueue.Count; if (cou > 100) { break; } } var localQueue = new Queue <WriteAsyncInfo>(); long localQueueThrowException(Exception exception) { long counter = 0; while (localQueue.Any()) { var witem = localQueue.Dequeue(); if (exception != null) { witem.TaskCompletionSource?.TrySetException(exception); } else { witem.TaskCompletionSource?.TrySetCanceled(); } counter = Interlocked.Decrement(ref _writeCounter); } return(counter); } var iswait = _writeCounter > 1; if (iswait) { Thread.CurrentThread.Join(10); } _begin(); while (true) { if (_writeQueue.Any() == false) { Thread.CurrentThread.Join(10); continue; } lock (_writeAsyncLock) { while (_writeQueue.TryDequeue(out var wq)) { localQueue.Enqueue(wq); } _bufferStream.Position = 0; try { _bufferStream.CopyTo(_rds.Stream); _bufferStream.Close(); _bufferStream.Dispose(); _bufferStream = null; } catch (Exception ioex) { localQueueThrowException(ioex); _bufferStream.Close(); _bufferStream.Dispose(); _bufferStream = null; _rds.ReleaseSocket(); _end(_rds, ioex); throw ioex; } } long counter = 0; RedisResult rt = null; //sb.AppendLine($"{name} 线程{Thread.CurrentThread.ManagedThreadId}:合并读取 {localQueue.Count} 个命令 total:{sw.ElapsedMilliseconds} ms"); while (localQueue.Any()) { var witem = localQueue.Dequeue(); try { rt = _rds.Read(false); } catch (Exception ioex) { localQueueThrowException(ioex); _rds.ReleaseSocket(); _end(_rds, ioex); throw ioex; } witem.TaskCompletionSource.TrySetResult(rt); counter = Interlocked.Decrement(ref _writeCounter); } if (counter == 0 && _finish()) { break; } Thread.CurrentThread.Join(1); //sb.AppendLine($"{name} 线程{Thread.CurrentThread.ManagedThreadId}:等待 1ms + {_writeQueue.Count} total:{sw.ElapsedMilliseconds} ms"); } //sb.AppendLine($"{name} 线程{Thread.CurrentThread.ManagedThreadId}:退出 total:{sw.ElapsedMilliseconds} ms"); _end(_rds, null); } return(ret); }
internal IDisposable Subscribe(bool psub, string[] channels, Action <string, string, object> handler) { if (_stoped) { return(new PubSubSubscribeDisposable(this, null)); } channels = channels?.Distinct().Where(a => !string.IsNullOrEmpty(a)).ToArray(); //In case of external modification if (channels?.Any() != true) { return(new PubSubSubscribeDisposable(this, null)); } var id = Guid.NewGuid(); var time = DateTime.Now; var regkeys = channels.Select(a => psub ? $"{_psub_regkey_prefix}{a}" : a).ToArray(); for (var a = 0; a < regkeys.Length; a++) { ConcurrentDictionary <Guid, RegisterInfo> dict = null; lock (_lock) dict = _registers.GetOrAdd(regkeys[a], k1 => new ConcurrentDictionary <Guid, RegisterInfo>()); dict.TryAdd(id, new RegisterInfo(id, handler, time)); } lock (_lock) _cancels.TryAdd(id, regkeys); var isnew = false; if (IsSubscribed == false) { lock (_lock) { if (IsSubscribed == false) { _redisSocket = _topOwner.Adapter.GetRedisSocket(null); IsSubscribed = isnew = true; } } } if (isnew) { new Thread(() => { _redisSocketReceiveTimeoutOld = _redisSocket.ReceiveTimeout; _redisSocket.ReceiveTimeout = TimeSpan.Zero; var timer = new Timer(state => { _topOwner.Adapter.Refersh(_redisSocket); //防止 IdleBus 超时回收 try { _redisSocket.Write("PING"); } catch { } }, null, 10000, 10000); var readCmd = "PubSubRead".SubCommand(null).FlagReadbytes(false); while (_stoped == false) { RedisResult rt = null; try { rt = _redisSocket.Read(readCmd); } catch { Thread.CurrentThread.Join(100); if (_cancels.Any()) { continue; } break; } var val = rt.Value as object[]; if (val == null) { continue; //special case } var val1 = val[0].ConvertTo <string>(); switch (val1) { case "pong": case "punsubscribe": case "unsubscribe": continue; case "pmessage": OnData(val[1].ConvertTo <string>(), val[2].ConvertTo <string>(), val[3]); continue; case "message": OnData(null, val[1].ConvertTo <string>(), val[2]); continue; } } timer.Dispose(); lock (_lock) { IsSubscribed = false; _redisSocket.ReceiveTimeout = _redisSocketReceiveTimeoutOld; _redisSocket.ReleaseSocket(); _redisSocket.Dispose(); _redisSocket = null; } }).Start(); } Call((psub ? "PSUBSCRIBE" : "SUBSCRIBE").Input(channels)); return(new PubSubSubscribeDisposable(this, () => Cancel(id))); }