Пример #1
0
 public void PublishCollectorPullEvent(CollectorPullEvent newEvent)
 {
     this.PublishEvent(newEvent,
                       this.config.collectorTopic,
                       this.config.pullEventFilter);
 }
Пример #2
0
        private async void timerEvent(Object source, ElapsedEventArgs arg)
        {
            // prevent calling this method again until the current execution is done
            // in case timer.Interval is shorter than the time required to pull data
            // from all the sensors
            timer.Stop();

            ConfigFields config = ServiceConfiguration.Instance;

            List <SensorRegistryRecord> availableSensors =
                await mediator.Send(new GetAllSensorsRequest());

            int triedToPullCount = 0;

            Console.WriteLine($"Available sensors count: {availableSensors.Count} ... ");
            foreach (var singleSensor in availableSensors)
            {
                long alreadyReadCount = 0;
                if (!lastReadIndexes.TryGetValue(
                        singleSensor.Name,
                        out alreadyReadCount))
                {
                    // get the count of already read records from this sensor
                    // db access
                    alreadyReadCount = await mediator
                                       .Send(new GetRecordsCountRequest(singleSensor.Name));

                    if (alreadyReadCount == -1)
                    {
                        Console.WriteLine("Failed to get read count for: "
                                          + $"{singleSensor.Name}");
                        // something went wrong
                        // most possibly failed to connect with the db

                        continue;                         // read from the next senor
                    }

                    lastReadIndexes.Add(singleSensor.Name, alreadyReadCount);
                }

                if (alreadyReadCount >= singleSensor.AvailableRecords)
                {
                    long diff = alreadyReadCount - singleSensor.AvailableRecords;
                    Console.WriteLine($"{singleSensor.Name} -> no new records "
                                      + $"waiting for: {diff} reads ... ");

                    continue;                     // read from the next sensor
                }

                string sensorAddr = $"http://{singleSensor.Address}:{singleSensor.Port}";
                string api_url    = $"{sensorAddr}/{config.dataRangeUrl}?"
                                    + $"sensorName={singleSensor.Name}&"
                                    + $"index={alreadyReadCount}";

                Uri sensorUri = new Uri(api_url);
                Console.Write($"{singleSensor.Name}@{sensorAddr} "
                              + $" | from: {alreadyReadCount} -> ");

                HttpResponseMessage response = null;
                try
                {
                    triedToPullCount++;
                    response = await this.httpClient.GetAsync(sensorUri);
                }
                catch (AggregateException e)
                {
                    // most possibly this exception happened because data pulling
                    // is started with old list of sensors
                    // sensors are removed from registry (shutdown events are received)
                    // after 'current sensors list is returned'
                    if (e.InnerException is HttpRequestException)
                    {
                        string message =
                            ((HttpRequestException)e.InnerException).Message;

                        Console.WriteLine(
                            $"\nHttp req. exception, message: {message} ... "
                            + $"sensor may be down.\n"
                            + $"Sensor addr. : {sensorUri.ToString()}\n");

                        var newEvent = new CollectorPullEvent(
                            config.serviceId,
                            sensorUri.ToString(),
                            false,
                            0,
                            e.Message);

                        // handler for this request is not async
                        // but i guess it is a good idea to await it anyway
                        await mediator.Send(new PublishCollectorPullEventRequest(newEvent));

                        continue;                         // pull from the next sensor
                    }
                }
                catch (HttpRequestException e)
                {
                    // same handler as for above catch ...
                    // i guess aggregateException is removed after some update
                    string message = e.Message;

                    Console.WriteLine(
                        $"\nHttp req. exception, message: {message} ... "
                        + $"sensor may be down.\n"
                        + $"Sensor addr. : {sensorUri.ToString()}\n");

                    var newEvent = new CollectorPullEvent(
                        config.serviceId,
                        sensorUri.ToString(),
                        false,
                        0,
                        e.Message);

                    // handler for this request is not async
                    // but i guess it is a good idea to await it anyway
                    await mediator.Send(new PublishCollectorPullEventRequest(newEvent));

                    continue;                     // pull from the next sensor
                }
                catch (Exception e)
                {
                    Console.WriteLine($"Unexpected exception while pulling data: "
                                      + $" {e.ToString()}");
                    continue;                     // pull from the next sensor
                }

                if (response == null || !response.IsSuccessStatusCode)
                {
                    // this will continue previous Console.Write( ... );
                    Console.WriteLine($" bad response ... ");

                    var newEvent = new CollectorPullEvent(
                        config.serviceId,
                        sensorUri.ToString(),
                        false,
                        0,
                        "Sensor returned bad response.");

                    // handler for this request is not async
                    // but i guess it is a good idea to await it anyway
                    await mediator.Send(new PublishCollectorPullEventRequest(newEvent));

                    continue;                     // pull from the next sensor
                }

                string txtContent = await response.Content.ReadAsStringAsync();

                // var dataRecords = System
                //      .Text
                //      .Json
                //      .JsonSerializer
                //      .Deserialize<SensorDataRecords>(txtResponseContent);
                // newtonsoft serializes properties to camelCase so when they get
                // pulled from sensor system.text.json can't deserialize it because
                // class properties are actually in PascalCase, that is the reason
                // to use newtonsoft - easier than forcing it to serialize in PascalCase

                var dataRecords = JsonConvert
                                  .DeserializeObject <SensorDataRecords>(txtContent);

                Console.WriteLine($"returned {dataRecords.RecordsCount} rows ... ");

                var pullEvent = new CollectorPullEvent(
                    config.serviceId,
                    sensorUri.ToString(),
                    true,
                    dataRecords.RecordsCount);

                await mediator.Send(new PublishCollectorPullEventRequest(pullEvent));

                var addResult = await mediator.Send(
                    new AddRecordsToSensorRequest(
                        singleSensor.Name,
                        dataRecords.CsvHeader,
                        dataRecords.CsvValues)
                    );

                if (addResult != true)
                {
                    // adding the new records was not successfull
                    // most possibly database is down ...
                    // this records will have to be pulled again

                    continue;
                }

                // update read index for every sensor that returned records
                // at this point lastReadIndex[singleSensor.Name] has to exists
                // (look at the beginning of this for loop)
                lastReadIndexes[singleSensor.Name] =
                    alreadyReadCount + dataRecords.RecordsCount;
            }

            Console.WriteLine($"Tried to pull from: {triedToPullCount} ...");
            // 'schedule' the next data pulling
            timer.Start();
        }
 public PublishCollectorPullEventRequest(CollectorPullEvent pullEvent)
 {
     this.pullEvent = pullEvent;
 }