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 RedisClientPool(string connectionString, Action <RedisClient> connected, RedisClient topOwner) : base(null) { _policy = new RedisClientPoolPolicy { _pool = this }; _policy.Connected += (s, o) => { var cli = s as RedisClient; var rds = cli.Adapter.GetRedisSocket(null); var adapter = cli.Adapter as RedisClient.SingleInsideAdapter; rds.Socket.ReceiveTimeout = (int)_policy._connectionStringBuilder.ReceiveTimeout.TotalMilliseconds; rds.Socket.SendTimeout = (int)_policy._connectionStringBuilder.SendTimeout.TotalMilliseconds; rds.Encoding = _policy._connectionStringBuilder.Encoding; var cmds = new List <CommandPacket>(); if (_policy._connectionStringBuilder.Protocol == RedisProtocol.RESP3) { cmds.Add("HELLO" .Input(3) .InputIf(!string.IsNullOrWhiteSpace(_policy._connectionStringBuilder.User) && !string.IsNullOrWhiteSpace(_policy._connectionStringBuilder.Password), "AUTH", _policy._connectionStringBuilder.User, _policy._connectionStringBuilder.Password) .InputIf(!string.IsNullOrWhiteSpace(_policy._connectionStringBuilder.ClientName), "SETNAME", _policy._connectionStringBuilder.ClientName) .OnData(rt => { rt.ThrowOrNothing(); rds.Protocol = RedisProtocol.RESP3; })); } else if (!string.IsNullOrEmpty(_policy._connectionStringBuilder.User) && !string.IsNullOrEmpty(_policy._connectionStringBuilder.Password)) { cmds.Add("AUTH".SubCommand(null) .InputIf(!string.IsNullOrWhiteSpace(_policy._connectionStringBuilder.User), _policy._connectionStringBuilder.User) .Input(_policy._connectionStringBuilder.Password) .OnData(rt => { rt.ThrowOrNothing(); })); } else if (!string.IsNullOrEmpty(_policy._connectionStringBuilder.Password)) { cmds.Add("AUTH".SubCommand(null) .Input(_policy._connectionStringBuilder.Password) .OnData(rt => { if (rt.IsError && rt.SimpleError != "ERR Client sent AUTH, but no password is set") { rt.ThrowOrNothing(); } })); } if (_policy._connectionStringBuilder.Database > 0) { cmds.Add("SELECT".Input(_policy._connectionStringBuilder.Database) .OnData(rt => { if (rt.IsError) { if (rt.SimpleError == "ERR SELECT is not allowed in cluster mode") { _policy._connectionStringBuilder.Database = 0; } else { rt.ThrowOrNothing(); } } (rds as IRedisSocketModify).SetDatabase(_policy._connectionStringBuilder.Database); })); } if (!string.IsNullOrEmpty(_policy._connectionStringBuilder.ClientName) && _policy._connectionStringBuilder.Protocol == RedisProtocol.RESP2) { cmds.Add("CLIENT".SubCommand("SETNAME").InputRaw(_policy._connectionStringBuilder.ClientName) .OnData(rt => { rt.ThrowOrNothing(); })); } cmds.Add("CLIENT".SubCommand("ID") .OnData(rt => { if (rt.IsError) { return; //ERR Syntax error, try CLIENT (LIST | KILL | GETNAME | SETNAME | PAUSE | REPLY) } (rds as IRedisSocketModify).SetClientId(rt.ThrowOrValue <long>()); })); using (var ms = new MemoryStream()) { var writer = new RespHelper.Resp3Writer(ms, rds.Encoding, RedisProtocol.RESP2); cmds.ForEach(cmd => { cmd.WriteHost = rds.Host; writer.WriteCommand(cmd); }); ms.Position = 0; ms.CopyTo(rds.Stream); ms.Close(); ms.Dispose(); } cmds.ForEach(cmd => { topOwner.LogCall(cmd, () => { var rt = rds.Read(cmd); return(rt.Value); }); }); connected?.Invoke(cli); topOwner?.OnConnected(TopOwner, new ConnectedEventArgs(_policy._connectionStringBuilder.Host, this, cli)); topOwner?.OnNotice(TopOwner, new NoticeEventArgs(NoticeType.Info, null, $"{_policy._connectionStringBuilder.Host.PadRight(21)} > Connected, ClientId: {rds.ClientId}, Database: {rds.Database}, Pool: {_freeObjects.Count}/{_allObjects.Count}", cli)); }; this.Policy = _policy; this.TopOwner = topOwner; _policy.ConnectionString = connectionString; }