mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 07:50:04 +00:00
Add text event pruning
- Still need to prune AlertLayer - Still need to test alerts reload after being pruned
This commit is contained in:
parent
4719badc54
commit
f37a77a9f7
6 changed files with 158 additions and 8 deletions
|
|
@ -138,8 +138,10 @@ common::Coordinate AlertManager::Impl::CurrentCoordinate(
|
|||
void AlertManager::Impl::HandleAlert(const types::TextEventKey& key,
|
||||
size_t messageIndex) const
|
||||
{
|
||||
auto messages = textEventManager_->message_list(key);
|
||||
|
||||
// Skip alert if there are more messages to be processed
|
||||
if (messageIndex + 1 < textEventManager_->message_count(key))
|
||||
if (messages.empty() || messageIndex + 1 < messages.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -153,7 +155,7 @@ void AlertManager::Impl::HandleAlert(const types::TextEventKey& key,
|
|||
audioSettings.alert_radius().GetValue());
|
||||
std::string alertWFO = audioSettings.alert_wfo().GetValue();
|
||||
|
||||
auto message = textEventManager_->message_list(key).at(messageIndex);
|
||||
auto message = messages.at(messageIndex);
|
||||
|
||||
for (auto& segment : message->segments())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -116,13 +116,14 @@ public:
|
|||
Impl(const Impl&&) = delete;
|
||||
Impl& operator=(const Impl&&) = delete;
|
||||
|
||||
void
|
||||
HandleMessage(const std::shared_ptr<awips::TextProductMessage>& message);
|
||||
void HandleMessage(const std::shared_ptr<awips::TextProductMessage>& message,
|
||||
bool archiveEvent = false);
|
||||
template<ranges::forward_range DateRange>
|
||||
requires std::same_as<ranges::range_value_t<DateRange>,
|
||||
std::chrono::sys_days>
|
||||
void ListArchives(DateRange dates);
|
||||
void LoadArchives(std::chrono::system_clock::time_point dateTime);
|
||||
void PruneArchives();
|
||||
void RefreshAsync();
|
||||
void Refresh();
|
||||
template<ranges::forward_range DateRange>
|
||||
|
|
@ -155,6 +156,15 @@ public:
|
|||
std::mutex archiveMutex_ {};
|
||||
std::list<std::chrono::sys_days> archiveDates_ {};
|
||||
|
||||
std::mutex archiveEventKeyMutex_ {};
|
||||
std::map<std::chrono::sys_days,
|
||||
std::unordered_set<types::TextEventKey,
|
||||
types::TextEventHash<types::TextEventKey>>>
|
||||
archiveEventKeys_ {};
|
||||
std::unordered_set<types::TextEventKey,
|
||||
types::TextEventHash<types::TextEventKey>>
|
||||
liveEventKeys_ {};
|
||||
|
||||
std::mutex unloadedProductMapMutex_ {};
|
||||
std::map<std::chrono::sys_days,
|
||||
boost::container::stable_vector<scwx::types::iem::AfosEntry>>
|
||||
|
|
@ -249,7 +259,7 @@ void TextEventManager::SelectTime(
|
|||
const auto today = std::chrono::floor<std::chrono::days>(dateTime);
|
||||
const auto yesterday = today - std::chrono::days {1};
|
||||
const auto tomorrow = today + std::chrono::days {1};
|
||||
const auto dateArray = std::array {today, yesterday, tomorrow};
|
||||
const auto dateArray = std::array {yesterday, today, tomorrow};
|
||||
|
||||
const auto dates =
|
||||
dateArray |
|
||||
|
|
@ -265,6 +275,7 @@ void TextEventManager::SelectTime(
|
|||
p->UpdateArchiveDates(dates);
|
||||
p->ListArchives(dates);
|
||||
p->LoadArchives(dateTime);
|
||||
p->PruneArchives();
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
|
|
@ -274,7 +285,7 @@ void TextEventManager::SelectTime(
|
|||
}
|
||||
|
||||
void TextEventManager::Impl::HandleMessage(
|
||||
const std::shared_ptr<awips::TextProductMessage>& message)
|
||||
const std::shared_ptr<awips::TextProductMessage>& message, bool archiveEvent)
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
|
|
@ -335,6 +346,12 @@ void TextEventManager::Impl::HandleMessage(
|
|||
textEventMap_.emplace(key, std::vector {message});
|
||||
messageIndex = 0;
|
||||
updated = true;
|
||||
|
||||
if (!archiveEvent)
|
||||
{
|
||||
// Add the Text Event Key to the list of live events to prevent pruning
|
||||
liveEventKeys_.insert(key);
|
||||
}
|
||||
}
|
||||
else if (std::find_if(it->second.cbegin(),
|
||||
it->second.cend(),
|
||||
|
|
@ -368,6 +385,17 @@ void TextEventManager::Impl::HandleMessage(
|
|||
updated = true;
|
||||
};
|
||||
|
||||
// If this is an archive event, and the key does not exist in the live events
|
||||
// Assumption: A live event will always be loaded before a duplicate archive
|
||||
// event
|
||||
if (archiveEvent && !liveEventKeys_.contains(key))
|
||||
{
|
||||
// Add the Text Event Key to the current date's archive
|
||||
const std::unique_lock archiveEventKeyLock {archiveEventKeyMutex_};
|
||||
auto& archiveKeys = archiveEventKeys_[wmoDate];
|
||||
archiveKeys.insert(key);
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
|
||||
if (updated)
|
||||
|
|
@ -518,11 +546,87 @@ void TextEventManager::Impl::LoadArchives(
|
|||
|
||||
for (auto& message : messages)
|
||||
{
|
||||
HandleMessage(message);
|
||||
HandleMessage(message, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextEventManager::Impl::PruneArchives()
|
||||
{
|
||||
static constexpr std::size_t kMaxArchiveDates_ = 5;
|
||||
|
||||
std::unordered_set<types::TextEventKey,
|
||||
types::TextEventHash<types::TextEventKey>>
|
||||
eventKeysToKeep {};
|
||||
std::unordered_set<types::TextEventKey,
|
||||
types::TextEventHash<types::TextEventKey>>
|
||||
eventKeysToPrune {};
|
||||
|
||||
// Remove oldest dates from the archive
|
||||
while (archiveDates_.size() > kMaxArchiveDates_)
|
||||
{
|
||||
archiveDates_.pop_front();
|
||||
}
|
||||
|
||||
const std::unique_lock archiveEventKeyLock {archiveEventKeyMutex_};
|
||||
|
||||
// If there are the same number of dates in both archiveEventKeys_ and
|
||||
// archiveDates_, there is nothing to prune
|
||||
if (archiveEventKeys_.size() == archiveDates_.size())
|
||||
{
|
||||
// Nothing to prune
|
||||
return;
|
||||
}
|
||||
|
||||
const std::unique_lock unloadedProductMapLock {unloadedProductMapMutex_};
|
||||
|
||||
for (auto it = archiveEventKeys_.begin(); it != archiveEventKeys_.end();)
|
||||
{
|
||||
const auto& date = it->first;
|
||||
const auto& eventKeys = it->second;
|
||||
|
||||
// If date is not in recent days map
|
||||
if (std::find(archiveDates_.cbegin(), archiveDates_.cend(), date) ==
|
||||
archiveDates_.cend())
|
||||
{
|
||||
// Prune these keys (unless they are in the eventKeysToKeep set)
|
||||
eventKeysToPrune.insert(eventKeys.begin(), eventKeys.end());
|
||||
|
||||
// The date is not in the list of recent dates, remove it
|
||||
it = archiveEventKeys_.erase(it);
|
||||
unloadedProductMap_.erase(date);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure these keys don't get pruned
|
||||
eventKeysToKeep.insert(eventKeys.begin(), eventKeys.end());
|
||||
|
||||
// The date is recent, keep it
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove elements from eventKeysToPrune if they are in eventKeysToKeep
|
||||
for (const auto& eventKey : eventKeysToKeep)
|
||||
{
|
||||
eventKeysToPrune.erase(eventKey);
|
||||
}
|
||||
|
||||
// Remove eventKeysToPrune from textEventMap
|
||||
for (const auto& eventKey : eventKeysToPrune)
|
||||
{
|
||||
textEventMap_.erase(eventKey);
|
||||
}
|
||||
|
||||
// If event keys were pruned, emit a signal
|
||||
if (!eventKeysToPrune.empty())
|
||||
{
|
||||
logger_->debug("Pruned {} archive events", eventKeysToPrune.size());
|
||||
|
||||
Q_EMIT self_->AlertsRemoved(eventKeysToPrune);
|
||||
}
|
||||
}
|
||||
|
||||
void TextEventManager::Impl::RefreshAsync()
|
||||
{
|
||||
boost::asio::post(threadPool_,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <QObject>
|
||||
|
|
@ -35,6 +36,10 @@ public:
|
|||
static std::shared_ptr<TextEventManager> Instance();
|
||||
|
||||
signals:
|
||||
void AlertsRemoved(
|
||||
const std::unordered_set<types::TextEventKey,
|
||||
types::TextEventHash<types::TextEventKey>>&
|
||||
keys);
|
||||
void AlertUpdated(const types::TextEventKey& key,
|
||||
std::size_t messageIndex,
|
||||
boost::uuids::uuid uuid);
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ void AlertModel::HandleAlert(const types::TextEventKey& alertKey,
|
|||
auto alertMessages = p->textEventManager_->message_list(alertKey);
|
||||
|
||||
// Skip alert if this is not the most recent message
|
||||
if (messageIndex + 1 < alertMessages.size())
|
||||
if (alertMessages.empty() || messageIndex + 1 < alertMessages.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -393,6 +393,35 @@ void AlertModel::HandleAlert(const types::TextEventKey& alertKey,
|
|||
}
|
||||
}
|
||||
|
||||
void AlertModel::HandleAlertsRemoved(
|
||||
const std::unordered_set<types::TextEventKey,
|
||||
types::TextEventHash<types::TextEventKey>>&
|
||||
alertKeys)
|
||||
{
|
||||
logger_->trace("Handle alerts removed");
|
||||
|
||||
for (const auto& alertKey : alertKeys)
|
||||
{
|
||||
// Remove from the list of text event keys
|
||||
auto it = std::find(
|
||||
p->textEventKeys_.begin(), p->textEventKeys_.end(), alertKey);
|
||||
if (it != p->textEventKeys_.end())
|
||||
{
|
||||
int row = std::distance(p->textEventKeys_.begin(), it);
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
p->textEventKeys_.erase(it);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
// Remove from internal maps
|
||||
p->observedMap_.erase(alertKey);
|
||||
p->threatCategoryMap_.erase(alertKey);
|
||||
p->tornadoPossibleMap_.erase(alertKey);
|
||||
p->centroidMap_.erase(alertKey);
|
||||
p->distanceMap_.erase(alertKey);
|
||||
}
|
||||
}
|
||||
|
||||
void AlertModel::HandleMapUpdate(double latitude, double longitude)
|
||||
{
|
||||
logger_->trace("Handle map update: {}, {}", latitude, longitude);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <scwx/common/geographic.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
|
|
@ -51,6 +52,10 @@ public:
|
|||
|
||||
public slots:
|
||||
void HandleAlert(const types::TextEventKey& alertKey, size_t messageIndex);
|
||||
void HandleAlertsRemoved(
|
||||
const std::unordered_set<types::TextEventKey,
|
||||
types::TextEventHash<types::TextEventKey>>&
|
||||
alertKeys);
|
||||
void HandleMapUpdate(double latitude, double longitude);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -131,6 +131,11 @@ void AlertDockWidgetImpl::ConnectSignals()
|
|||
&QAction::toggled,
|
||||
proxyModel_.get(),
|
||||
&model::AlertProxyModel::SetAlertActiveFilter);
|
||||
connect(textEventManager_.get(),
|
||||
&manager::TextEventManager::AlertsRemoved,
|
||||
alertModel_.get(),
|
||||
&model::AlertModel::HandleAlertsRemoved,
|
||||
Qt::QueuedConnection);
|
||||
connect(textEventManager_.get(),
|
||||
&manager::TextEventManager::AlertUpdated,
|
||||
alertModel_.get(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue