mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 14:50:05 +00:00
Don't reload archive text products that have already been loaded
This commit is contained in:
parent
cc54e4d834
commit
33cfd4bc0e
4 changed files with 87 additions and 15 deletions
|
|
@ -5,7 +5,10 @@
|
||||||
#include <scwx/provider/iem_api_provider.hpp>
|
#include <scwx/provider/iem_api_provider.hpp>
|
||||||
#include <scwx/provider/warnings_provider.hpp>
|
#include <scwx/provider/warnings_provider.hpp>
|
||||||
#include <scwx/util/logger.hpp>
|
#include <scwx/util/logger.hpp>
|
||||||
|
#include <scwx/util/time.hpp>
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
@ -90,6 +93,7 @@ public:
|
||||||
void LoadArchives(std::chrono::sys_days date);
|
void LoadArchives(std::chrono::sys_days date);
|
||||||
void RefreshAsync();
|
void RefreshAsync();
|
||||||
void Refresh();
|
void Refresh();
|
||||||
|
void UpdateArchiveDates(std::chrono::sys_days date);
|
||||||
|
|
||||||
// Thread pool sized for:
|
// Thread pool sized for:
|
||||||
// - Live Refresh (1x)
|
// - Live Refresh (1x)
|
||||||
|
|
@ -112,9 +116,18 @@ public:
|
||||||
std::unique_ptr<provider::IemApiProvider> iemApiProvider_ {
|
std::unique_ptr<provider::IemApiProvider> iemApiProvider_ {
|
||||||
std::make_unique<provider::IemApiProvider>()};
|
std::make_unique<provider::IemApiProvider>()};
|
||||||
std::shared_ptr<provider::WarningsProvider> warningsProvider_ {nullptr};
|
std::shared_ptr<provider::WarningsProvider> warningsProvider_ {nullptr};
|
||||||
|
|
||||||
std::chrono::hours loadHistoryDuration_ {kInitialLoadHistoryDuration_};
|
std::chrono::hours loadHistoryDuration_ {kInitialLoadHistoryDuration_};
|
||||||
std::chrono::sys_time<std::chrono::hours> prevLoadTime_ {};
|
std::chrono::sys_time<std::chrono::hours> prevLoadTime_ {};
|
||||||
|
|
||||||
|
std::mutex archiveMutex_ {};
|
||||||
|
std::list<std::chrono::sys_days> archiveDates_ {};
|
||||||
|
std::map<
|
||||||
|
std::chrono::sys_days,
|
||||||
|
std::unordered_map<std::string,
|
||||||
|
std::vector<std::shared_ptr<awips::TextProductFile>>>>
|
||||||
|
archiveMap_;
|
||||||
|
|
||||||
boost::uuids::uuid warningsProviderChangedCallbackUuid_ {};
|
boost::uuids::uuid warningsProviderChangedCallbackUuid_ {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -187,10 +200,12 @@ void TextEventManager::LoadFile(const std::string& filename)
|
||||||
void TextEventManager::SelectTime(
|
void TextEventManager::SelectTime(
|
||||||
std::chrono::system_clock::time_point dateTime)
|
std::chrono::system_clock::time_point dateTime)
|
||||||
{
|
{
|
||||||
|
logger_->trace("Select Time: {}", util::TimeString(dateTime));
|
||||||
|
|
||||||
const auto today = std::chrono::floor<std::chrono::days>(dateTime);
|
const auto today = std::chrono::floor<std::chrono::days>(dateTime);
|
||||||
const auto yesterday = today - std::chrono::days {1};
|
const auto yesterday = today - std::chrono::days {1};
|
||||||
const auto tomorrow = today + std::chrono::days {1};
|
const auto tomorrow = today + std::chrono::days {1};
|
||||||
const auto dates = {yesterday, today, tomorrow};
|
const auto dates = {today, yesterday, tomorrow};
|
||||||
|
|
||||||
for (auto& date : dates)
|
for (auto& date : dates)
|
||||||
{
|
{
|
||||||
|
|
@ -279,8 +294,26 @@ void TextEventManager::Impl::HandleMessage(
|
||||||
void TextEventManager::Impl::LoadArchive(std::chrono::sys_days date,
|
void TextEventManager::Impl::LoadArchive(std::chrono::sys_days date,
|
||||||
const std::string& pil)
|
const std::string& pil)
|
||||||
{
|
{
|
||||||
|
std::unique_lock lock {archiveMutex_};
|
||||||
|
auto& dateArchive = archiveMap_[date];
|
||||||
|
if (dateArchive.contains(pil))
|
||||||
|
{
|
||||||
|
// Don't reload data that has already been loaded
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
logger_->debug("Load Archive: {}, {}", util::TimeString(date), pil);
|
||||||
|
|
||||||
|
// Query for products
|
||||||
const auto& productIds = iemApiProvider_->ListTextProducts(date, {}, pil);
|
const auto& productIds = iemApiProvider_->ListTextProducts(date, {}, pil);
|
||||||
const auto& products = iemApiProvider_->LoadTextProducts(productIds);
|
|
||||||
|
if (productIds.has_value())
|
||||||
|
{
|
||||||
|
logger_->debug("Loading {} {} products", productIds.value().size(), pil);
|
||||||
|
|
||||||
|
// Load listed products
|
||||||
|
auto products = iemApiProvider_->LoadTextProducts(productIds.value());
|
||||||
|
|
||||||
for (auto& product : products)
|
for (auto& product : products)
|
||||||
{
|
{
|
||||||
|
|
@ -291,10 +324,26 @@ void TextEventManager::Impl::LoadArchive(std::chrono::sys_days date,
|
||||||
HandleMessage(message);
|
HandleMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
// Ensure the archive map still contains the date, and has not been pruned
|
||||||
|
if (archiveMap_.contains(date))
|
||||||
|
{
|
||||||
|
// Store the products associated with the PIL in the archive
|
||||||
|
dateArchive.try_emplace(pil, std::move(products));
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEventManager::Impl::LoadArchives(std::chrono::sys_days date)
|
void TextEventManager::Impl::LoadArchives(std::chrono::sys_days date)
|
||||||
{
|
{
|
||||||
|
logger_->trace("Load Archives: {}", util::TimeString(date));
|
||||||
|
|
||||||
|
UpdateArchiveDates(date);
|
||||||
|
|
||||||
for (auto& pil : kPils_)
|
for (auto& pil : kPils_)
|
||||||
{
|
{
|
||||||
boost::asio::post(threadPool_,
|
boost::asio::post(threadPool_,
|
||||||
|
|
@ -380,6 +429,15 @@ void TextEventManager::Impl::Refresh()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextEventManager::Impl::UpdateArchiveDates(std::chrono::sys_days date)
|
||||||
|
{
|
||||||
|
std::unique_lock lock {archiveMutex_};
|
||||||
|
|
||||||
|
// Remove any existing occurrences of day, and add to the back of the list
|
||||||
|
archiveDates_.remove(date);
|
||||||
|
archiveDates_.push_back(date);
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<TextEventManager> TextEventManager::Instance()
|
std::shared_ptr<TextEventManager> TextEventManager::Instance()
|
||||||
{
|
{
|
||||||
static std::weak_ptr<TextEventManager> textEventManagerReference_ {};
|
static std::weak_ptr<TextEventManager> textEventManagerReference_ {};
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,16 @@ TEST(IemApiProviderTest, ListTextProducts)
|
||||||
|
|
||||||
auto torProducts = provider.ListTextProducts(date, {}, "TOR");
|
auto torProducts = provider.ListTextProducts(date, {}, "TOR");
|
||||||
|
|
||||||
EXPECT_EQ(torProducts.size(), 35);
|
ASSERT_EQ(torProducts.has_value(), true);
|
||||||
|
EXPECT_EQ(torProducts.value().size(), 35);
|
||||||
|
|
||||||
if (torProducts.size() >= 1)
|
if (torProducts.value().size() >= 1)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(torProducts.at(0), "202303250016-KMEG-WFUS54-TORMEG");
|
EXPECT_EQ(torProducts.value().at(0), "202303250016-KMEG-WFUS54-TORMEG");
|
||||||
}
|
}
|
||||||
if (torProducts.size() >= 35)
|
if (torProducts.value().size() >= 35)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(torProducts.at(34), "202303252015-KFFC-WFUS52-TORFFC");
|
EXPECT_EQ(torProducts.value().at(34), "202303252015-KFFC-WFUS52-TORFFC");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/outcome/result.hpp>
|
||||||
|
|
||||||
namespace scwx::provider
|
namespace scwx::provider
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -23,7 +25,7 @@ public:
|
||||||
IemApiProvider(IemApiProvider&&) noexcept;
|
IemApiProvider(IemApiProvider&&) noexcept;
|
||||||
IemApiProvider& operator=(IemApiProvider&&) noexcept;
|
IemApiProvider& operator=(IemApiProvider&&) noexcept;
|
||||||
|
|
||||||
static std::vector<std::string>
|
static boost::outcome_v2::result<std::vector<std::string>>
|
||||||
ListTextProducts(std::chrono::sys_time<std::chrono::days> date,
|
ListTextProducts(std::chrono::sys_time<std::chrono::days> date,
|
||||||
std::optional<std::string_view> cccc = {},
|
std::optional<std::string_view> cccc = {},
|
||||||
std::optional<std::string_view> pil = {});
|
std::optional<std::string_view> pil = {});
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ IemApiProvider::~IemApiProvider() = default;
|
||||||
IemApiProvider::IemApiProvider(IemApiProvider&&) noexcept = default;
|
IemApiProvider::IemApiProvider(IemApiProvider&&) noexcept = default;
|
||||||
IemApiProvider& IemApiProvider::operator=(IemApiProvider&&) noexcept = default;
|
IemApiProvider& IemApiProvider::operator=(IemApiProvider&&) noexcept = default;
|
||||||
|
|
||||||
std::vector<std::string>
|
boost::outcome_v2::result<std::vector<std::string>>
|
||||||
IemApiProvider::ListTextProducts(std::chrono::sys_time<std::chrono::days> date,
|
IemApiProvider::ListTextProducts(std::chrono::sys_time<std::chrono::days> date,
|
||||||
std::optional<std::string_view> cccc,
|
std::optional<std::string_view> cccc,
|
||||||
std::optional<std::string_view> pil)
|
std::optional<std::string_view> pil)
|
||||||
|
|
@ -93,6 +93,8 @@ IemApiProvider::ListTextProducts(std::chrono::sys_time<std::chrono::days> date,
|
||||||
{
|
{
|
||||||
// Unexpected bad response
|
// Unexpected bad response
|
||||||
logger_->warn("Error parsing JSON: {}", ex.what());
|
logger_->warn("Error parsing JSON: {}", ex.what());
|
||||||
|
return boost::system::errc::make_error_code(
|
||||||
|
boost::system::errc::bad_message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (response.status_code == cpr::status::HTTP_BAD_REQUEST &&
|
else if (response.status_code == cpr::status::HTTP_BAD_REQUEST &&
|
||||||
|
|
@ -109,6 +111,9 @@ IemApiProvider::ListTextProducts(std::chrono::sys_time<std::chrono::days> date,
|
||||||
// Unexpected bad response
|
// Unexpected bad response
|
||||||
logger_->warn("Error parsing bad response: {}", ex.what());
|
logger_->warn("Error parsing bad response: {}", ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return boost::system::errc::make_error_code(
|
||||||
|
boost::system::errc::invalid_argument);
|
||||||
}
|
}
|
||||||
else if (response.status_code == cpr::status::HTTP_UNPROCESSABLE_ENTITY &&
|
else if (response.status_code == cpr::status::HTTP_UNPROCESSABLE_ENTITY &&
|
||||||
json != nullptr)
|
json != nullptr)
|
||||||
|
|
@ -125,10 +130,16 @@ IemApiProvider::ListTextProducts(std::chrono::sys_time<std::chrono::days> date,
|
||||||
// Unexpected bad response
|
// Unexpected bad response
|
||||||
logger_->warn("Error parsing validation error: {}", ex.what());
|
logger_->warn("Error parsing validation error: {}", ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return boost::system::errc::make_error_code(
|
||||||
|
boost::system::errc::no_message_available);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger_->warn("Could not list text products: {}", response.status_line);
|
logger_->warn("Could not list text products: {}", response.status_line);
|
||||||
|
|
||||||
|
return boost::system::errc::make_error_code(
|
||||||
|
boost::system::errc::no_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return textProducts;
|
return textProducts;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue