Ejemplo n.º 1
0
        public async Task <TResponse> Handle <TResponse>(IClusterRequest <TResponse> request) where TResponse : BaseResponse, new()
        {
            _logger.LogDebug(_nodeStateService.GetNodeLogId() + "Detected RPC " + request.GetType().Name + "." + Environment.NewLine + JsonConvert.SerializeObject(request, Formatting.Indented));
            if (!_nodeStateService.IsBootstrapped)
            {
                _logger.LogDebug(_nodeStateService.GetNodeLogId() + "Node is not ready...");

                return(new TResponse()
                {
                    IsSuccessful = false,
                    ErrorMessage = "Node is not ready..."
                });
            }

            if (IsClusterRequest <TResponse>(request) && !_nodeStateService.InCluster)
            {
                _logger.LogWarning(_nodeStateService.GetNodeLogId() + "Reqeuest rejected, node is not apart of cluster...");
                return(new TResponse()
                {
                    IsSuccessful = false,
                    ErrorMessage = "Node is not apart of cluster..."
                });
            }

            DateTime commandStartTime = DateTime.Now;

            try
            {
                TResponse response;
                switch (request)
                {
                case ExecuteCommands t1:
                    response = await HandleIfLeaderOrReroute(request, async() => (TResponse)(object)await _raftService.Handle(t1));

                    break;

                case RequestVote t1:
                    response = (TResponse)(object)await _raftService.Handle(t1);

                    break;

                case AppendEntry t1:
                    response = (TResponse)(object)await _raftService.Handle(t1);

                    break;

                case InstallSnapshot t1:
                    response = (TResponse)(object)await _raftService.Handle(t1);

                    break;

                case RequestCreateIndex t1:
                    response = await HandleIfLeaderOrReroute(request, async() => (TResponse)(object)await _dataService.Handle(t1));

                    break;

                case AddShardWriteOperation t1:
                    response = (TResponse)(object)await _dataService.Handle(t1);

                    break;

                case RequestDataShard t1:
                    response = (TResponse)(object)await _dataService.Handle(t1);

                    break;

                case AllocateShard t1:
                    response = (TResponse)(object)await _dataService.Handle(t1);

                    break;

                case ReplicateShardWriteOperation t1:
                    response = (TResponse)(object)await _dataService.Handle(t1);

                    break;

                case RequestShardWriteOperations t1:
                    response = (TResponse)(object)await _dataService.Handle(t1);

                    break;

                default:
                    throw new Exception("Request is not implemented");
                }

                if (MetricGenerated != null && _nodeStateService.Role == NodeState.Leader && request.Metric)
                {
                    //Add and send
                    if (!lastMetricGenerated.ContainsKey(request.RequestName))
                    {
                        lastMetricGenerated.TryAdd(request.RequestName, DateTime.Now);
                        MetricGenerated.Invoke(this, new Metric()
                        {
                            Date       = DateTime.Now,
                            IntervalMs = 0,
                            Type       = MetricTypes.ClusterCommandElapsed(request.RequestName),
                            Value      = (DateTime.Now - commandStartTime).TotalMilliseconds
                        });
                    }
                    else if ((DateTime.Now - lastMetricGenerated[request.RequestName]).TotalMilliseconds > _clusterOptions.MetricsIntervalMs)
                    {
                        lastMetricGenerated.TryUpdate(request.RequestName, DateTime.Now, lastMetricGenerated[request.RequestName]);
                        MetricGenerated.Invoke(this, new Metric()
                        {
                            Date       = DateTime.Now,
                            IntervalMs = 0,
                            Type       = MetricTypes.ClusterCommandElapsed(request.RequestName),
                            Value      = (DateTime.Now - commandStartTime).TotalMilliseconds
                        });
                    }
                }

                return(response);
            }
            catch (TaskCanceledException e)
            {
                _logger.LogWarning(_nodeStateService.GetNodeLogId() + "Request " + request.RequestName + " timed out...");
                return(new TResponse()
                {
                    IsSuccessful = false
                });
            }
            catch (Exception e)
            {
                _logger.LogError(_nodeStateService.GetNodeLogId() + "Failed to handle request " + request.RequestName + " with error " + e.Message + Environment.StackTrace + e.StackTrace);
                return(new TResponse()
                {
                    IsSuccessful = false
                });
            }
        }
Ejemplo n.º 2
0
        public async Task <TResponse> HandleIfLeaderOrReroute <TResponse>(IClusterRequest <TResponse> request, Func <Task <TResponse> > Handle) where TResponse : BaseResponse, new()
        {
            var CurrentTime = DateTime.Now;

            // if you change and become a leader, just handle this yourself.
            if (_nodeStateService.Role != NodeState.Leader)
            {
                // Candidate, not in cluster or you still think current leader is yourself.
                if (_nodeStateService.Role == NodeState.Candidate || !_nodeStateService.InCluster || _nodeStateService.Id == _nodeStateService.CurrentLeader.Value)
                {
                    /* if ((DateTime.Now - CurrentTime).TotalMilliseconds < _clusterOptions.LatencyToleranceMs)
                     * {
                     *   _logger.LogWarning(_nodeStateService.GetNodeLogId() + "Currently a candidate during routing, will sleep thread and try again.");
                     *   Thread.Sleep(1000);
                     * }
                     * else
                     * {*/
                    return(new TResponse()
                    {
                        IsSuccessful = false
                    });
                    //}
                }
                else
                {
                    try
                    {
                        _logger.LogDebug(_nodeStateService.GetNodeLogId() + "Detected routing of command " + request.GetType().Name + " to leader.");
                        return((TResponse)(object)await _clusterClient.Send(_nodeStateService.CurrentLeader.Value, request));
                    }
                    catch (Exception e)
                    {
                        _logger.LogError(_nodeStateService.GetNodeLogId() + "Encountered " + e.Message + " while trying to route " + request.GetType().Name + " to leader.");
                        return(new TResponse()
                        {
                            IsSuccessful = false
                        });
                    }
                }
            }
            return(await Handle());
        }