Integrate Warnings Provider auto-refresh into Text Event Manager

This commit is contained in:
Dan Paulat 2022-11-06 23:39:01 -06:00
parent a2616b0ee0
commit c7a69a76be
7 changed files with 131 additions and 36 deletions

View file

@ -1,11 +1,14 @@
#include <scwx/qt/manager/text_event_manager.hpp>
#include <scwx/awips/text_product_file.hpp>
#include <scwx/provider/warnings_provider.hpp>
#include <scwx/util/logger.hpp>
#include <scwx/util/threads.hpp>
#include <shared_mutex>
#include <unordered_map>
#include <boost/asio/steady_timer.hpp>
namespace scwx
{
namespace qt
@ -16,25 +19,44 @@ namespace manager
static const std::string logPrefix_ = "scwx::qt::manager::text_event_manager";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
static const std::string& kDefaultWarningsProviderUrl {
"https://warnings.allisonhouse.com"};
class TextEventManager::Impl
{
public:
explicit Impl(TextEventManager* self) :
self_ {self}, textEventMap_ {}, textEventMutex_ {}
self_ {self},
refreshTimer_ {util::io_context()},
refreshMutex_ {},
textEventMap_ {},
textEventMutex_ {},
warningsProvider_ {kDefaultWarningsProviderUrl}
{
util::async([=]() { Refresh(); });
}
~Impl() {}
~Impl()
{
std::unique_lock lock(refreshMutex_);
refreshTimer_.cancel();
}
void HandleMessage(std::shared_ptr<awips::TextProductMessage> message);
void Refresh();
TextEventManager* self_;
boost::asio::steady_timer refreshTimer_;
std::mutex refreshMutex_;
std::unordered_map<types::TextEventKey,
std::vector<std::shared_ptr<awips::TextProductMessage>>,
types::TextEventHash<types::TextEventKey>>
textEventMap_;
std::shared_mutex textEventMutex_;
provider::WarningsProvider warningsProvider_;
};
TextEventManager::TextEventManager() : p(std::make_unique<Impl>(this)) {}
@ -159,10 +181,74 @@ void TextEventManager::Impl::HandleMessage(
}
}
TextEventManager& TextEventManager::Instance()
void TextEventManager::Impl::Refresh()
{
static TextEventManager textEventManager_ {};
return textEventManager_;
using namespace std::chrono;
logger_->trace("Refresh");
// Take a unique lock before refreshing
std::unique_lock lock(refreshMutex_);
// Set threshold to last 30 hours
auto newerThan = std::chrono::system_clock::now() - 30h;
// Update the file listing from the warnings provider
auto [newFiles, totalFiles] = warningsProvider_.ListFiles(newerThan);
if (newFiles > 0)
{
// Load new files
auto updatedFiles = warningsProvider_.LoadUpdatedFiles(newerThan);
// Handle messages
for (auto& file : updatedFiles)
{
for (auto& message : file->messages())
{
HandleMessage(message);
}
}
}
// Schedule another update in 15 seconds
using namespace std::chrono;
refreshTimer_.expires_after(15s);
refreshTimer_.async_wait(
[=](const boost::system::error_code& e)
{
if (e == boost::asio::error::operation_aborted)
{
logger_->debug("Refresh timer cancelled");
}
else if (e != boost::system::errc::success)
{
logger_->warn("Refresh timer error: {}", e.message());
}
else
{
Refresh();
}
});
}
std::shared_ptr<TextEventManager> TextEventManager::Instance()
{
static std::weak_ptr<TextEventManager> textEventManagerReference_ {};
static std::mutex instanceMutex_ {};
std::unique_lock lock(instanceMutex_);
std::shared_ptr<TextEventManager> textEventManager =
textEventManagerReference_.lock();
if (textEventManager == nullptr)
{
textEventManager = std::make_shared<TextEventManager>();
textEventManagerReference_ = textEventManager;
}
return textEventManager;
}
} // namespace manager

View file

@ -29,7 +29,7 @@ public:
void LoadFile(const std::string& filename);
static TextEventManager& Instance();
static std::shared_ptr<TextEventManager> Instance();
signals:
void AlertUpdated(const types::TextEventKey& key, size_t messageIndex);