/// <summary> /// Sends data to Ingress restful end point /// </summary> /// <param name="state">Object state</param> private static void FlushToIngress(object state) { // Flush to ingress if more than 10 telemetry recordings -or- last flush older that 1 minute if (_globalQueue.Count <= 10 && DateTime.UtcNow - _lastFlush <= new TimeSpan(0, 1, 0)) { Console.WriteLine($"Not flushing: {_globalQueue.Count} Queued - {(DateTime.UtcNow - _lastFlush).TotalSeconds} seconds since flush"); return; } List <string> telemetryToSend = new List <string>(); while (telemetryToSend.Count < 50 && _globalQueue.TryDequeue(out string lineFromQueue)) { telemetryToSend.Add(lineFromQueue); } Console.WriteLine($"Flushing {telemetryToSend.Count} to ingress. {_globalQueue.Count} still in queue." + (_flushHighspeed ? " [HighSpeed]" : "")); TelemetryPacket pkt = new TelemetryPacket { NodeId = _configuration.NodeId, Payload = telemetryToSend, Signature = _signer.SignPayload(string.Join(string.Empty, telemetryToSend)) }; string jsonPayload = JsonConvert.SerializeObject(pkt); // Send data TalkToIngress tti = new TalkToIngress(_configuration.IngressHost + "/api/ingress/influx", _configuration.IngressFingerprint); bool sendSuccess = tti.SendRequest(jsonPayload).Result; if (!sendSuccess) { if (DateTime.UtcNow - _lastFlush > TimeSpan.FromMinutes(5)) { // unable to send to ingress for 5 minutes - send by second channel Console.WriteLine("ERROR: Unable to send to ingress for more then 5 minutes. Sending queue on second channel."); string fileName = $"{_configuration.NodeId}-{DateTime.UtcNow:yyyy-MM-dd_HH:mm:ss}.json"; try { if (!_ftpMgr.TransferData(jsonPayload, fileName)) { Console.WriteLine("ERROR: Unable to send data on second channel. Data File {0}", fileName); // second channel also not available - requeue Console.WriteLine("Unable to flush to second channel - re queueing"); telemetryToSend.ForEach(_globalQueue.Enqueue); } } catch (Exception ex) { Console.WriteLine("ERROR: Unable to send data on second channel. Error Details {0}", ex); // second channel also not available - requeue Console.WriteLine("Unable to flush to second channel - re queueing"); telemetryToSend.ForEach(_globalQueue.Enqueue); } } else { // 5min second channel delay not reached -> re-queue Console.WriteLine("Unable to flush. Re-queuing..."); telemetryToSend.ForEach(_globalQueue.Enqueue); } } else { if (_globalQueue.Count > 250 && !_flushHighspeed) { // increase processing speed to 2 seconds Console.WriteLine("Increasing push speed due to queue size"); _flushTimer.Change(2000, 2000); _flushHighspeed = true; } else if (_globalQueue.Count < 250 && _flushHighspeed) // queue is small enough to get processed. back to normal speed { Console.WriteLine("Decreasing push speed due to queue size"); _flushTimer.Change(10000, 10000); _flushHighspeed = false; } _lastFlush = DateTime.UtcNow; } }
/// <summary> /// Function for parsing and signing block data /// </summary> /// <param name="buffer">block data in byte array</param> /// <returns>returns instance of RealTimeTelemetry if valid data is provided else null</returns> private RealTimeTelemetry ParseAndSignData(byte[] buffer) { try { string numPeers = GetCurrentNumPeers(); string clientVersion = GetCurrentClientVersion(); dynamic jsonObj = JsonConvert.DeserializeObject(_encoder.GetString(buffer).Trim()); dynamic paramsObj = jsonObj["params"]; if (paramsObj != null && paramsObj["result"] != null) { dynamic resultObj = paramsObj["result"]; string gasLimit = resultObj["gasLimit"]; string gasUsed = resultObj["gasUsed"]; long currentEPoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; RealTimeTelemetryPayload rttp = new RealTimeTelemetryPayload { Client = clientVersion, BlockNum = Convert.ToUInt64(resultObj["number"].ToString(), 16), BlockHash = resultObj["hash"].ToString(), BlockTS = Convert.ToInt64(resultObj["timestamp"].ToString(), 16), BlockReceived = currentEPoch, NumPeers = Convert.ToUInt16(numPeers, 16), NumTxInBlock = (ushort)resultObj["transactions"].Count, GasLimit = Convert.ToInt64(gasLimit, 16), GasUsed = Convert.ToInt64(gasUsed, 16) }; RealTimeTelemetry rtt = new RealTimeTelemetry { NodeId = _nodeId, Payload = rttp, Signature = _signer.SignPayload(JsonConvert.SerializeObject(rttp)) }; if (_verbose) { Console.WriteLine("New Block received"); Console.WriteLine("block num: {0}", rttp.BlockNum); Console.WriteLine("block hash: {0}", rttp.BlockHash); Console.WriteLine("block time stamp: {0}", rttp.BlockTS); Console.WriteLine("Tx Count: {0}", rttp.NumTxInBlock); Console.WriteLine("Gas Limit: {0}", Convert.ToInt64(gasLimit, 16)); Console.WriteLine("Gas Used: {0}", Convert.ToInt64(gasUsed, 16)); Console.WriteLine("Peers: {0} ", rttp.NumPeers); } return(rtt); } Console.WriteLine("Unable to Parse\\Sign real Time data. Invalid Data"); } catch (Exception ex) { Console.WriteLine("Unable to Parse\\Sign real Time data. Error Occurred {0}", ex); } return(null); }