private async Task UpdateLastStateEntry(HostsRepository hostsrepo, HostStatesRepository staterepo, EventRepository eventrepo, CancellationToken stoppingToken)
        {
            var hosts = await hostsrepo.GetAllActive();

            await hosts.ForEachAsync(10, async (host) =>
            {
                await UpdateSingleHostStateEntry(hostsrepo, staterepo, eventrepo, host);
            });
        }
        private async Task CreateStateEntries(HostsRepository hostsrepo, HostStatesRepository staterepo)
        {
            var states = (await hostsrepo.GetAllActive())
                         .Select(x => new HostState {
                HostId = x.Id
            });

            staterepo.Add(states);
        }
        internal async Task <bool> LoopProcessor(EventRepository eventrepo, TagsRepository tagrepo, HostStatesRepository staterepo)
        {
            if (!eventrepo.HasElements)
            {
                return(false);
            }

            var appevent = await eventrepo.Dequeue();

            if (appevent == null)
            {
                return(true);
            }

            switch (appevent)
            {
            case TagAddedEvent evt:
                await ProcessTagAddedEvent(tagrepo, evt);

                break;

            case TagRemovedEvent evt:
                break;

            case HostOnlineEvent evt:
                if (staterepo
                    .GetForHost(evt.HostId, 5)
                    .All(x =>
                         x.Status == HostState.StatusEnum.Online ||
                         x.Status == HostState.StatusEnum.Warning ||
                         x.Status == HostState.StatusEnum.Critical) &&
                    !(await tagrepo.GetTagsForHost(evt.HostId)).Any(x => x.Name == "online"))
                {
                    if (!(await tagrepo.GetTagsForHost(evt.HostId)).Any(x => x.Name == "offline"))
                    {
                        break;
                    }

                    await tagrepo.AddTagToHost("online", evt.HostId);

                    await tagrepo.RemoveTagFromHost("offline", evt.HostId);
                }
                break;

            case HostOfflineEvent evt:
                if (staterepo
                    .GetForHost(evt.HostId, 5)
                    .All(x => x.Status == HostState.StatusEnum.Offline) &&
                    !(await tagrepo.GetTagsForHost(evt.HostId)).Any(x => x.Name == "offline"))
                {
                    await tagrepo.AddTagToHost("offline", evt.HostId);

                    await tagrepo.RemoveTagFromHost("online", evt.HostId);
                }
                break;

            default:
                _logger.LogError($"Unknown event type {appevent.ToString()}");
                break;
            }

            return(true);
        }
        private async Task UpdateSingleHostStateEntry(HostsRepository hostsrepo, HostStatesRepository staterepo, EventRepository eventrepo, Data.Host host)
        {
            _logger.LogTrace($"Checking host {host.Name} ({host.Hostname})");

            var state = staterepo.GetForHost(host.Id)
                        .Last();

            var ping = new Ping();

            try
            {
                var reply = await ping.SendPingAsync(host.Hostname, 2000);

                switch (reply.Status)
                {
                case IPStatus.Success:
                    state.Delay = (int)reply.RoundtripTime;
                    switch (reply.RoundtripTime)
                    {
                    case long n when n < 70:
                        state.Status = HostState.StatusEnum.Online;
                        break;

                    case long n when n < 300:
                        state.Status = HostState.StatusEnum.Warning;
                        break;

                    case long n when n < 2000:
                        state.Status = HostState.StatusEnum.Critical;
                        break;

                    default:
                        state.Status = HostState.StatusEnum.Error;
                        break;
                    }

                    await eventrepo.Enqueue(new HostOnlineEvent { HostId = host.Id });

                    break;

                case IPStatus.TimedOut:
                    state.Status = HostState.StatusEnum.Offline;
                    await eventrepo.Enqueue(new HostOfflineEvent { HostId = host.Id });

                    break;

                default:
                    _logger.LogError($"Unknown IPStatus {reply.Status} while checking {host.Hostname}");
                    state.Status = HostState.StatusEnum.Error;
                    break;
                }
            }
            catch (Exception)
            {
                _logger.LogWarning($"Error while checking {host.Name} ({host.Hostname})");
                state.Status = HostState.StatusEnum.Error;
            }
            finally
            {
                _logger.LogTrace($"Check complete for host {host.Name} ({host.Hostname})");
            }
        }