Ejemplo n.º 1
0
        /// <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);
        }