public bool IsClusterRequest <TResponse>(IClusterRequest <TResponse> request) where TResponse : BaseResponse { switch (request) { case ExecuteCommands t1: return(true); case RequestCreateIndex t1: return(true); case AddShardWriteOperation t1: return(true); case RequestDataShard t1: return(true); case AllocateShard t1: return(true); case ReplicateShardWriteOperation t1: return(true); case RequestShardWriteOperations t1: return(true); default: return(false); } }
public async Task <IActionResult> PostRPC([FromBody] IClusterRequest <BaseResponse> request) { if (request == null) { Logger.LogError("FOR SOME REASON THE REQUEST IS NULL"); } return(Ok(await _handler.Handle(request))); }
public async Task <TResponse> Send <TResponse>(IClusterRequest <TResponse> request) where TResponse : BaseResponse { HttpResponseMessage result; switch (request) { case AddShardWriteOperation t1: result = await PostAsJsonAsync(_dataClient, "/api/node/RPC", request); break; case RequestShardWriteOperations t1: result = await PostAsJsonAsync(_dataClient, "/api/node/RPC", request); break; case RequestCreateIndex t1: result = await PostAsJsonAsync(_dataClient, "/api/node/RPC", request); break; case ReplicateShardWriteOperation t1: result = await PostAsJsonAsync(_dataClient, "/api/node/RPC", request); break; default: result = await PostAsJsonAsync(_httpClient, "/api/node/RPC", request); break; } try { if (result.IsSuccessStatusCode) { return(JsonConvert.DeserializeObject <TResponse>(await result.Content.ReadAsStringAsync())); } else { throw new Exception("Failed to send request with status code " + result.StatusCode + "."); } } catch (Exception e) { throw e; } }
public async Task <TResponse> Send <TResponse>(Guid nodeId, IClusterRequest <TResponse> request) where TResponse : BaseResponse, new() { //if the request is for yourself if (_nodeStateService.Id == nodeId) { return(await Send(request)); } if (_clusterConnectionPool.ContainsNode(nodeId)) { return(await _clusterConnectionPool.GetNodeClient(nodeId).Send(request)); } else { throw new MissingNodeConnectionDetailsException("Node " + nodeId + " was not found in available connections."); } }
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()); }
public async Task <TResponse> Handle <TResponse>(IClusterRequest <TResponse> request) where TResponse : BaseResponse, new() { DateTime commandStartTime = DateTime.Now; TResponse response; switch (request) { case ExecuteCommands t1: response = (TResponse)(object) await ExecuteCommandsRPCHandler(t1); break; case RequestVote t1: response = (TResponse)(object)RequestVoteRPCHandler(t1); break; case AppendEntry t1: response = (TResponse)(object)AppendEntryRPCHandler(t1); break; case InstallSnapshot t1: response = (TResponse)(object)InstallSnapshotHandler(t1); break; default: throw new Exception("Request is not implemented"); } if (response != null) { return(response); } return(new TResponse() { IsSuccessful = false, ErrorMessage = "Response is null" }); }
public async Task <TResponse> Handle <TResponse>(IClusterRequest <TResponse> request) where TResponse : BaseResponse, new() { try { DateTime commandStartTime = DateTime.Now; TResponse response; switch (request) { case RequestDataShard t1: response = (TResponse)(object) await RequestDataShardHandler(t1); break; case AddShardWriteOperation t1: response = (TResponse)(object) await AddShardWriteOperationHandler(t1); break; case RequestCreateIndex t1: response = (TResponse)(object) await RequestCreateIndexHandler(t1); break; case AllocateShard t1: response = (TResponse)(object) await AllocateShardHandler(t1); break; case ReplicateShardWriteOperation t1: response = (TResponse)(object) await ReplicateShardWriteOperationHandler(t1); break; case RequestShardWriteOperations t1: response = (TResponse)(object) await RequestShardWriteOperationsHandler(t1); break; case RequestShardSync t1: response = (TResponse)(object) await RequestShardSyncHandler(t1); break; default: throw new Exception("Request is not implemented"); } 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 }); } }
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 }); } }
public async Task <TResponse> Send <TResponse>(IClusterRequest <TResponse> request) where TResponse : BaseResponse, new() { return(await _clusterRequestHandler.Handle(request)); }