Пример #1
0
 public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     return(TopOwner.LogCall(cmd, () =>
     {
         RedisResult rt = null;
         RedisClientPool pool = null;
         Exception ioex = null;
         using (var rds = GetRedisSocket(cmd))
         {
             pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
             try
             {
                 rds.Write(cmd);
                 rt = rds.Read(cmd._flagReadbytes);
             }
             catch (Exception ex)
             {
                 ioex = ex;
             }
         }
         if (ioex != null)
         {
             if (pool?.SetUnavailable(ioex) == true)
             {
             }
             throw ioex;
         }
         return parse(rt);
     }));
 }
Пример #2
0
 public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     return(TopOwner.LogCall(cmd, () =>
     {
         RedisResult rt = null;
         using (var rds = GetRedisSocket(cmd))
         {
             try
             {
                 rds.Write(cmd);
                 rt = rds.Read(cmd);
             }
             catch (Exception ex)
             {
                 var pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
                 if (pool?.SetUnavailable(ex) == true)
                 {
                     Interlocked.Exchange(ref _masterHost, null);
                     RecoverySentinel();
                 }
                 throw ex;
             }
         }
         return parse(rt);
     }));
 }
Пример #3
0
 public override Task <TValue> AdapterCallAsync <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     return(TopOwner.LogCallAsync(cmd, async() =>
     {
         var asyncRds = _asyncManager.GetAsyncRedisSocket(cmd);
         try
         {
             var rt = await asyncRds.WriteAsync(cmd);
             return parse(rt);
         }
         catch (ProtocolViolationException)
         {
             var pool = (asyncRds._rds as DefaultRedisSocket.TempProxyRedisSocket)?._pool;
             cmd._protocolErrorTryCount++;
             if (pool != null && cmd._protocolErrorTryCount <= pool._policy._connectionStringBuilder.Retry)
             {
                 return await AdapterCallAsync(cmd, parse);
             }
             else
             {
                 if (cmd.IsReadOnlyCommand() == false || cmd._protocolErrorTryCount > 1)
                 {
                     throw;
                 }
                 return await AdapterCallAsync(cmd, parse);
             }
         }
     }));
 }
Пример #4
0
            async public override Task <TValue> AdapterCallAsync <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
            {
                var poolkey = GetIdleBusKey(cmd);
                var pool    = _ib.Get(poolkey);

                if (pool.AsyncSocket == null)
                {
                    return(AdapterCall(cmd, parse));
                }
                return(await TopOwner.LogCallAsync(cmd, async() =>
                {
                    RedisResult rt = null;
                    Exception ioex = null;
                    try
                    {
                        rt = await pool.AsyncSocket.WriteAsync(cmd);
                    }
                    catch (Exception ex)
                    {
                        ioex = ex;
                    }
                    if (ioex != null)
                    {
                        if (pool?.SetUnavailable(ioex) == true)
                        {
                        }
                        throw ioex;
                    }
                    rt.IsErrorThrow = TopOwner._isThrowRedisSimpleError;
                    return parse(rt);
                }));
            }
Пример #5
0
            async public override Task <TValue> AdapterCallAsync <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
            {
                //Read with non byte[], Object deserialization is not supported
                //The value returned by the callback is null :
                //  tran.Get<Book>("key1").ContinueWith(t => t3 = t.Result)
                var tsc = new TaskCompletionSource <object>();

                TryMulti();
                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
                        }),
                        TaskCompletionSource = tsc
                    });
                    return(default(TValue));
                });
                var ret = await tsc.Task;

                return((TValue)ret);
            }
Пример #6
0
 object SelfCall(CommandPacket cmd)
 {
     return(TopOwner.LogCall(cmd, () =>
     {
         _redisSocket.Write(cmd);
         return _redisSocket.Read(false).ThrowOrValue();
     }));
 }
Пример #7
0
 object SelfCall(CommandPacket cmd)
 {
     return(TopOwner.LogCall(cmd, () =>
     {
         _redisSocket.Write(cmd);
         return cmd.Read <string>().ThrowOrValue();
     }));
 }
Пример #8
0
 public override Task <TValue> AdapterCallAsync <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     return(TopOwner.LogCallAsync(cmd, async() =>
     {
         var asyncRds = _asyncManager.GetAsyncRedisSocket(cmd);
         var rt = await asyncRds.WriteAsync(cmd);
         return parse(rt);
     }));
 }
Пример #9
0
            bool RecoverySentinel()
            {
                var ing = false;

                if (RecoverySentineling == false)
                {
                    lock (RecoverySentinelingLock)
                    {
                        if (RecoverySentineling == false)
                        {
                            RecoverySentineling = ing = true;
                        }
                    }
                }

                if (ing)
                {
                    new Thread(() =>
                    {
                        while (true)
                        {
                            Thread.CurrentThread.Join(1000);
                            try
                            {
                                ResetSentinel();

                                if (_ib.Get(_masterHost).CheckAvailable())
                                {
                                    if (!TopOwner.OnNotice(null, new NoticeEventArgs(NoticeType.Info, null, $"{_connectionString.Host.PadRight(21)} > Redis Sentinel switch to {_masterHost}", null)))
                                    {
                                        var bgcolor             = Console.BackgroundColor;
                                        var forecolor           = Console.ForegroundColor;
                                        Console.BackgroundColor = ConsoleColor.DarkGreen;
                                        Console.ForegroundColor = ConsoleColor.White;
                                        Console.Write($"【{_connectionString.Host}】Redis Sentinel switch to {_masterHost}");
                                        Console.BackgroundColor = bgcolor;
                                        Console.ForegroundColor = forecolor;
                                        Console.WriteLine();
                                    }

                                    RecoverySentineling = false;
                                    return;
                                }
                            }
                            catch (Exception ex21)
                            {
                                if (!TopOwner.OnNotice(null, new NoticeEventArgs(NoticeType.Info, null, $"{_connectionString.Host.PadRight(21)} > Redis Sentinel switch to {_masterHost}", null)))
                                {
                                    Console.WriteLine($"【{_connectionString.Host}】Redis Sentinel: {ex21.Message}");
                                }
                            }
                        }
                    }).Start();
                }
                return(ing);
            }
Пример #10
0
 public override TValue AdapaterCall <TReadTextOrStream, TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     return(TopOwner.LogCall(cmd, () =>
     {
         _redisSocket.Write(cmd);
         var rt = cmd.Read <TReadTextOrStream>();
         rt.IsErrorThrow = TopOwner._isThrowRedisSimpleError;
         return parse(rt);
     }));
 }
Пример #11
0
 public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     _commands.Add(new PipelineCommand
     {
         Command = cmd,
         Parse   = rt => parse(rt),
         IsBytes = cmd._flagReadbytes
     });
     TopOwner.OnNotice(new NoticeEventArgs(NoticeType.Call, null, $"Pipeline > {cmd}", null));
     return(default(TValue));
 }
Пример #12
0
 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);
     }));
 }
Пример #13
0
 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);
     }));
 }
Пример #14
0
 public override TValue AdapaterCall <TReadTextOrStream, TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     _commands.Add(new PipelineCommand
     {
         Command = cmd,
         Parse   = pc =>
         {
             var rt          = pc.Command.Read <TReadTextOrStream>();
             rt.IsErrorThrow = TopOwner._isThrowRedisSimpleError;
             return(parse(rt));
         }
     });
     TopOwner.OnNotice(new NoticeEventArgs(NoticeType.Call, null, $"Pipeline > {cmd}", null));
     return(default(TValue));
 }
Пример #15
0
            async public override Task <TValue> AdapterCallAsync <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
            {
                var tsc = new TaskCompletionSource <object>();

                _commands.Add(new PipelineCommand
                {
                    Command = cmd,
                    Parse   = rt => parse(rt),
                    IsBytes = cmd._flagReadbytes,
                    TaskCompletionSource = tsc
                });
                TopOwner.OnNotice(new NoticeEventArgs(NoticeType.Call, null, $"Pipeline > {cmd}", null));
                var ret = await tsc.Task;

                return((TValue)ret);
            }
Пример #16
0
 public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     return(TopOwner.LogCall(cmd, () =>
     {
         RedisResult rt = null;
         var protocolRetry = false;
         using (var rds = GetRedisSocket(cmd))
         {
             try
             {
                 rds.Write(cmd);
                 rt = rds.Read(cmd);
             }
             catch (ProtocolViolationException)
             {
                 var pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
                 rds.ReleaseSocket();
                 cmd._protocolErrorTryCount++;
                 if (cmd._protocolErrorTryCount <= pool._policy._connectionStringBuilder.Retry)
                 {
                     protocolRetry = true;
                 }
                 else
                 {
                     if (cmd.IsReadOnlyCommand() == false || cmd._protocolErrorTryCount > 1)
                     {
                         throw;
                     }
                     protocolRetry = true;
                 }
             }
             catch (Exception ex)
             {
                 var pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
                 if (pool?.SetUnavailable(ex) == true)
                 {
                 }
                 throw;
             }
         }
         if (protocolRetry)
         {
             return AdapterCall(cmd, parse);
         }
         return parse(rt);
     }));
 }
Пример #17
0
 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);
     }));
 }
Пример #18
0
            public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
            {
                if (cmd._keyIndexes.Count > 1) //Multiple key slot values not equal
                {
                    switch (cmd._command)
                    {
                    case "DEL":
                    case "UNLINK":
                        return(cmd._keyIndexes.Select((_, idx) => AdapterCall(new CommandPacket(cmd._command).InputKey(cmd.GetKey(idx)), parse)).Sum(a => a.ConvertTo <long>()).ConvertTo <TValue>());

                    case "MSET":
                        cmd._keyIndexes.ForEach(idx => AdapterCall(new CommandPacket(cmd._command).InputKey(cmd._input[idx].ToInvariantCultureToString()).InputRaw(cmd._input[idx + 1]), parse));
                        return(default);

                    case "MGET":
                        return(cmd._keyIndexes.Select((_, idx) => AdapterCall(new CommandPacket(cmd._command).InputKey(cmd.GetKey(idx)), parse).ConvertTo <object[]>().First()).ToArray().ConvertTo <TValue>());

                    case "PFCOUNT":
                        return(cmd._keyIndexes.Select((_, idx) => AdapterCall(new CommandPacket(cmd._command).InputKey(cmd.GetKey(idx)), parse)).Sum(a => a.ConvertTo <long>()).ConvertTo <TValue>());
                    }
                }
                return(TopOwner.LogCall(cmd, () =>
                {
                    RedisResult rt = null;
                    RedisClientPool pool = null;
                    using (var rds = GetRedisSocket(cmd))
                    {
                        pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
                        try
                        {
                            rds.Write(cmd);
                            rt = rds.Read(cmd);
                        }
                        catch (Exception ex)
                        {
                            if (pool?.SetUnavailable(ex) == true)
                            {
                            }
                            throw ex;
                        }
                    }
                    return parse(rt);
                }));
            }
Пример #19
0
 public override TValue AdapaterCall <TReadTextOrStream, TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
 {
     TryMulti();
     return(TopOwner.LogCall(cmd, () =>
     {
         _redisSocket.Write(cmd);
         cmd.Read <TReadTextOrStream>().ThrowOrValue <TValue>();
         cmd._readed = false; //exec 还需要再读一次
         _commands.Add(new TransactionCommand
         {
             Command = cmd,
             Parse = obj => parse(new RedisResult(obj, true, RedisMessageType.SimpleString)
             {
                 Encoding = _redisSocket.Encoding
             })
         });
         return default(TValue);
     }));
 }
Пример #20
0
            public object[] EndPipe()
            {
                if (_commands.Any() == false)
                {
                    return(new object[0]);
                }

                try
                {
                    switch (UseType)
                    {
                    case UseType.Pooling: break;

                    case UseType.Cluster: return(ClusterEndPipe());

                    case UseType.Sentinel:
                    case UseType.SingleInside: break;

                    case UseType.SingleTemp: break;
                    }

                    CommandPacket epcmd = "EndPipe";
                    return(TopOwner.LogCall(epcmd, () =>
                    {
                        using (var rds = TopOwner.Adapter.GetRedisSocket(null))
                        {
                            epcmd._redisSocket = rds;
                            EndPipe(rds, _commands);
                        }
                        return _commands.Select(a => a.Result).ToArray();
                    }));
                }
                finally
                {
                    _commands.Clear();
                }

                object[] ClusterEndPipe()
                {
                    throw new NotSupportedException();
                }
            }
Пример #21
0
            public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
            {
                return(TopOwner.LogCall(cmd, () =>
                {
                    RedisResult rt = null;
                    RedisClientPool pool = null;
                    using (var rds = GetRedisSocket(cmd))
                    {
                        pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
                        try
                        {
                            if (cmd._clusterMovedAsking)
                            {
                                cmd._clusterMovedAsking = false;
                                rds.Write("ASKING");
                                rds.Read(false);
                            }
                            rds.Write(cmd);
                            rt = rds.Read(cmd._flagReadbytes);
                        }
                        catch (Exception ex)
                        {
                            if (pool?.SetUnavailable(ex) == true)
                            {
                            }
                            throw ex;
                        }
                    }
                    if (rt.IsError && pool != null)
                    {
                        var moved = ClusterMoved.ParseSimpleError(rt.SimpleError);
                        if (moved != null && cmd._clusterMovedTryCount < 3)
                        {
                            cmd._clusterMovedTryCount++;

                            if (moved.endpoint.StartsWith("127.0.0.1"))
                            {
                                moved.endpoint = $"{DefaultRedisSocket.SplitHost(pool._policy._connectionStringBuilder.Host).Key}:{moved.endpoint.Substring(10)}";
                            }
                            else if (moved.endpoint.StartsWith("localhost", StringComparison.CurrentCultureIgnoreCase))
                            {
                                moved.endpoint = $"{DefaultRedisSocket.SplitHost(pool._policy._connectionStringBuilder.Host).Key}:{moved.endpoint.Substring(10)}";
                            }

                            ConnectionStringBuilder connectionString = pool._policy._connectionStringBuilder.ToString();
                            connectionString.Host = moved.endpoint;
                            RegisterClusterNode(connectionString);

                            if (moved.ismoved)
                            {
                                _slotCache.AddOrUpdate(moved.slot, connectionString.Host, (k1, v1) => connectionString.Host);
                            }

                            if (moved.isask)
                            {
                                cmd._clusterMovedAsking = true;
                            }

                            TopOwner.OnNotice(new NoticeEventArgs(NoticeType.Info, null, $"{(cmd.WriteHost ?? "Not connected")} > {cmd}\r\n{rt.SimpleError} ", null));
                            return AdapterCall(cmd, parse);
                        }
                    }
                    rt.IsErrorThrow = TopOwner._isThrowRedisSimpleError;
                    return parse(rt);
                }));
            }
Пример #22
0
            public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
            {
                if (cmd._keyIndexes.Count > 1) //Multiple key slot values not equal
                {
                    cmd.Prefix(TopOwner.Prefix);
                    switch (cmd._command)
                    {
                    case "DEL":
                    case "UNLINK":
                        return(cmd._keyIndexes.Select((_, idx) => AdapterCall(new CommandPacket(cmd._command).InputKey(cmd.GetKey(idx)), parse)).Sum(a => a.ConvertTo <long>()).ConvertTo <TValue>());

                    case "MSET":
                        cmd._keyIndexes.ForEach(idx => AdapterCall(new CommandPacket(cmd._command).InputKey(cmd._input[idx].ToInvariantCultureToString()).InputRaw(cmd._input[idx + 1]), parse));
                        return(default);

                    case "MGET":
                        return(cmd._keyIndexes.Select((_, idx) =>
                        {
                            var rt = AdapterCall(cmd._command.InputKey(cmd.GetKey(idx)), parse);
                            return rt.ConvertTo <object[]>().FirstOrDefault();
                        }).ToArray().ConvertTo <TValue>());

                    case "PFCOUNT":
                        return(cmd._keyIndexes.Select((_, idx) => AdapterCall(new CommandPacket(cmd._command).InputKey(cmd.GetKey(idx)), parse)).Sum(a => a.ConvertTo <long>()).ConvertTo <TValue>());
                    }
                }
                return(TopOwner.LogCall(cmd, () =>
                {
                    RedisResult rt = null;
                    var protocolRetry = false;
                    using (var rds = GetRedisSocket(cmd))
                    {
                        try
                        {
                            rds.Write(cmd);
                            rt = rds.Read(cmd);
                        }
                        catch (ProtocolViolationException)
                        {
                            var pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
                            rds.ReleaseSocket();
                            cmd._protocolErrorTryCount++;
                            if (cmd._protocolErrorTryCount <= pool._policy._connectionStringBuilder.Retry)
                            {
                                protocolRetry = true;
                            }
                            else
                            {
                                if (cmd.IsReadOnlyCommand() == false || cmd._protocolErrorTryCount > 1)
                                {
                                    throw;
                                }
                                protocolRetry = true;
                            }
                        }
                        catch (Exception ex)
                        {
                            var pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
                            if (pool?.SetUnavailable(ex) == true)
                            {
                            }
                            throw;
                        }
                    }
                    if (protocolRetry)
                    {
                        return AdapterCall(cmd, parse);
                    }
                    return parse(rt);
                }));
            }
Пример #23
0
            public override TValue AdapterCall <TValue>(CommandPacket cmd, Func <RedisResult, TValue> parse)
            {
                if (cmd._keyIndexes.Count > 1) //Multiple key slot values not equal
                {
                    switch (cmd._command)
                    {
                    case "DEL":
                    case "UNLINK":
                        return(cmd._keyIndexes.Select((_, idx) => AdapterCall(cmd._command.InputKey(cmd.GetKey(idx)), parse)).Sum(a => a.ConvertTo <long>()).ConvertTo <TValue>());

                    case "MSET":
                        cmd._keyIndexes.ForEach(idx => AdapterCall(cmd._command.InputKey(cmd._input[idx].ToInvariantCultureToString()).InputRaw(cmd._input[idx + 1]), parse));
                        return(default);

                    case "MGET":
                        return(cmd._keyIndexes.Select((_, idx) =>
                        {
                            var rt = AdapterCall(cmd._command.InputKey(cmd.GetKey(idx)), parse);
                            return rt.ConvertTo <object[]>().FirstOrDefault();
                        }).ToArray().ConvertTo <TValue>());

                    case "PFCOUNT":
                        return(cmd._keyIndexes.Select((_, idx) => AdapterCall(cmd._command.InputKey(cmd.GetKey(idx)), parse)).Sum(a => a.ConvertTo <long>()).ConvertTo <TValue>());
                    }
                }
                return(TopOwner.LogCall(cmd, () =>
                {
                    RedisResult rt = null;
                    RedisClientPool pool = null;
                    var protocolRetry = false;
                    using (var rds = GetRedisSocket(cmd))
                    {
                        pool = (rds as DefaultRedisSocket.TempProxyRedisSocket)._pool;
                        try
                        {
                            if (cmd._clusterMovedAsking)
                            {
                                cmd._clusterMovedAsking = false;
                                var askingCmd = "ASKING".SubCommand(null).FlagReadbytes(false);
                                rds.Write(askingCmd);
                                rds.Read(askingCmd);
                            }
                            rds.Write(cmd);
                            rt = rds.Read(cmd);
                        }
                        catch (ProtocolViolationException)
                        {
                            rds.ReleaseSocket();
                            cmd._protocolErrorTryCount++;
                            if (cmd._protocolErrorTryCount <= pool._policy._connectionStringBuilder.Retry)
                            {
                                protocolRetry = true;
                            }
                            else
                            {
                                if (cmd.IsReadOnlyCommand() == false || cmd._protocolErrorTryCount > 1)
                                {
                                    throw;
                                }
                                protocolRetry = true;
                            }
                        }
                        catch (Exception ex)
                        {
                            if (pool?.SetUnavailable(ex) == true)
                            {
                            }
                            throw;
                        }
                    }
                    if (protocolRetry)
                    {
                        return AdapterCall(cmd, parse);
                    }
                    if (rt.IsError && pool != null)
                    {
                        var moved = ClusterMoved.ParseSimpleError(rt.SimpleError);
                        if (moved != null && cmd._clusterMovedTryCount < 3)
                        {
                            cmd._clusterMovedTryCount++;

                            if (moved.endpoint.StartsWith("127.0.0.1"))
                            {
                                moved.endpoint = $"{DefaultRedisSocket.SplitHost(pool._policy._connectionStringBuilder.Host).Key}:{moved.endpoint.Substring(10)}";
                            }
                            else if (moved.endpoint.StartsWith("localhost", StringComparison.CurrentCultureIgnoreCase))
                            {
                                moved.endpoint = $"{DefaultRedisSocket.SplitHost(pool._policy._connectionStringBuilder.Host).Key}:{moved.endpoint.Substring(10)}";
                            }

                            ConnectionStringBuilder connectionString = pool._policy._connectionStringBuilder.ToString();
                            connectionString.Host = moved.endpoint;
                            RegisterClusterNode(connectionString);

                            if (moved.ismoved)
                            {
                                _slotCache.AddOrUpdate(moved.slot, connectionString.Host, (k1, v1) => connectionString.Host);
                            }

                            if (moved.isask)
                            {
                                cmd._clusterMovedAsking = true;
                            }

                            TopOwner.OnNotice(null, new NoticeEventArgs(NoticeType.Info, null, $"{(cmd.WriteTarget ?? "Not connected").PadRight(21)} > {cmd}\r\n{rt.SimpleError} ", null));
                            return AdapterCall(cmd, parse);
                        }
                    }
                    return parse(rt);
                }));
            }