Additional level 2 data provider functionality for display of latest data

This commit is contained in:
Dan Paulat 2022-05-28 02:04:59 -05:00
parent 57e5badd70
commit 4b9d12a7ef
3 changed files with 147 additions and 24 deletions

View file

@ -29,12 +29,19 @@ public:
size_t cache_size() const; size_t cache_size() const;
std::chrono::system_clock::time_point last_modified() const;
std::chrono::seconds update_period() const;
std::string FindKey(std::chrono::system_clock::time_point time); std::string FindKey(std::chrono::system_clock::time_point time);
std::string FindLatestKey();
std::pair<size_t, size_t> std::pair<size_t, size_t>
ListObjects(std::chrono::system_clock::time_point date); ListObjects(std::chrono::system_clock::time_point date);
std::shared_ptr<wsr88d::Ar2vFile> LoadObjectByKey(const std::string& key); std::shared_ptr<wsr88d::Ar2vFile> LoadObjectByKey(const std::string& key);
size_t Refresh(); size_t Refresh();
std::chrono::system_clock::time_point
GetTimePointByKey(const std::string& key) const;
static std::chrono::system_clock::time_point static std::chrono::system_clock::time_point
GetTimePointFromKey(const std::string& key); GetTimePointFromKey(const std::string& key);

View file

@ -27,6 +27,23 @@ public:
virtual size_t cache_size() const = 0; virtual size_t cache_size() const = 0;
/**
* Gets the last modified time. This is equal to the most recent object's
* modification time. If there are no objects, the epoch is returned.
*
* @return Last modified time
*/
virtual std::chrono::system_clock::time_point last_modified() const = 0;
/**
* Gets the current update period. This is equal to the difference between
* the last two objects' modification times. If there are less than two
* objects, an update period of 0 is returned.
*
* @return Update period
*/
virtual std::chrono::seconds update_period() const = 0;
/** /**
* Finds the most recent key in the cache, no later than the time provided. * Finds the most recent key in the cache, no later than the time provided.
* *
@ -36,6 +53,13 @@ public:
*/ */
virtual std::string FindKey(std::chrono::system_clock::time_point time) = 0; virtual std::string FindKey(std::chrono::system_clock::time_point time) = 0;
/**
* Finds the most recent key in the cache.
*
* @return Level 2 data key
*/
virtual std::string FindLatestKey() = 0;
/** /**
* Lists level 2 objects for the date supplied, and adds them to the cache. * Lists level 2 objects for the date supplied, and adds them to the cache.
* *
@ -66,6 +90,16 @@ public:
*/ */
virtual size_t Refresh() = 0; virtual size_t Refresh() = 0;
/**
* Convert the object key to a time point.
*
* @key Level 2 data key
*
* @return Level 2 data time point
*/
virtual std::chrono::system_clock::time_point
GetTimePointByKey(const std::string& key) const = 0;
private: private:
std::unique_ptr<Level2DataProviderImpl> p; std::unique_ptr<Level2DataProviderImpl> p;
}; };

View file

@ -27,6 +27,20 @@ static const std::string kDefaultRegion_ = "us-east-1";
class AwsLevel2DataProviderImpl class AwsLevel2DataProviderImpl
{ {
public: public:
struct ObjectRecord
{
explicit ObjectRecord(
const std::string& key,
std::chrono::system_clock::time_point lastModified) :
key_ {key}, lastModified_ {lastModified}
{
}
~ObjectRecord() = default;
std::string key_;
std::chrono::system_clock::time_point lastModified_;
};
explicit AwsLevel2DataProviderImpl(const std::string& radarSite, explicit AwsLevel2DataProviderImpl(const std::string& radarSite,
const std::string& bucketName, const std::string& bucketName,
const std::string& region) : const std::string& region) :
@ -35,7 +49,9 @@ public:
region_ {region}, region_ {region},
client_ {nullptr}, client_ {nullptr},
objects_ {}, objects_ {},
objectsMutex_ {} objectsMutex_ {},
lastModified_ {},
updatePeriod_ {}
{ {
Aws::Client::ClientConfiguration config; Aws::Client::ClientConfiguration config;
config.region = region_; config.region = region_;
@ -45,14 +61,19 @@ public:
~AwsLevel2DataProviderImpl() {} ~AwsLevel2DataProviderImpl() {}
void UpdateMetadata();
std::string radarSite_; std::string radarSite_;
std::string bucketName_; std::string bucketName_;
std::string region_; std::string region_;
std::unique_ptr<Aws::S3::S3Client> client_; std::unique_ptr<Aws::S3::S3Client> client_;
std::map<std::chrono::system_clock::time_point, std::string> objects_; std::map<std::chrono::system_clock::time_point, ObjectRecord> objects_;
std::shared_mutex objectsMutex_; std::shared_mutex objectsMutex_;
std::chrono::system_clock::time_point lastModified_;
std::chrono::seconds updatePeriod_;
}; };
AwsLevel2DataProvider::AwsLevel2DataProvider(const std::string& radarSite) : AwsLevel2DataProvider::AwsLevel2DataProvider(const std::string& radarSite) :
@ -78,6 +99,17 @@ size_t AwsLevel2DataProvider::cache_size() const
return p->objects_.size(); return p->objects_.size();
} }
std::chrono::seconds AwsLevel2DataProvider::update_period() const
{
return p->updatePeriod_;
}
std::chrono::system_clock::time_point
AwsLevel2DataProvider::last_modified() const
{
return p->lastModified_;
}
std::string std::string
AwsLevel2DataProvider::FindKey(std::chrono::system_clock::time_point time) AwsLevel2DataProvider::FindKey(std::chrono::system_clock::time_point time)
{ {
@ -87,12 +119,27 @@ AwsLevel2DataProvider::FindKey(std::chrono::system_clock::time_point time)
std::shared_lock lock(p->objectsMutex_); std::shared_lock lock(p->objectsMutex_);
std::optional<std::string> element = auto element = util::GetBoundedElement(p->objects_, time);
util::GetBoundedElement(p->objects_, time);
if (element.has_value()) if (element.has_value())
{ {
key = *element; key = element->key_;
}
return key;
}
std::string AwsLevel2DataProvider::FindLatestKey()
{
logger_->debug("FindLatestKey()");
std::string key {};
std::shared_lock lock(p->objectsMutex_);
if (!p->objects_.empty())
{
key = p->objects_.crbegin()->second.key_;
} }
return key; return key;
@ -122,7 +169,8 @@ AwsLevel2DataProvider::ListObjects(std::chrono::system_clock::time_point date)
logger_->debug("Found {} objects", objects.size()); logger_->debug("Found {} objects", objects.size());
// Store objects // Store objects
std::for_each(objects.cbegin(), std::for_each( //
objects.cbegin(),
objects.cend(), objects.cend(),
[&](const Aws::S3::Model::Object& object) [&](const Aws::S3::Model::Object& object)
{ {
@ -132,10 +180,16 @@ AwsLevel2DataProvider::ListObjects(std::chrono::system_clock::time_point date)
{ {
auto time = GetTimePointFromKey(key); auto time = GetTimePointFromKey(key);
std::chrono::seconds lastModifiedSeconds {
object.GetLastModified().Seconds()};
std::chrono::system_clock::time_point lastModified {
lastModifiedSeconds};
std::unique_lock lock(p->objectsMutex_); std::unique_lock lock(p->objectsMutex_);
auto [it, inserted] = auto [it, inserted] = p->objects_.insert_or_assign(
p->objects_.insert_or_assign(time, key); time,
AwsLevel2DataProviderImpl::ObjectRecord {key, lastModified});
if (inserted) if (inserted)
{ {
@ -152,6 +206,8 @@ AwsLevel2DataProvider::ListObjects(std::chrono::system_clock::time_point date)
outcome.GetError().GetMessage()); outcome.GetError().GetMessage());
} }
p->UpdateMetadata();
return std::make_pair(newObjects, totalObjects); return std::make_pair(newObjects, totalObjects);
} }
@ -222,6 +278,32 @@ size_t AwsLevel2DataProvider::Refresh()
return totalNewObjects; return totalNewObjects;
} }
void AwsLevel2DataProviderImpl::UpdateMetadata()
{
std::shared_lock lock(objectsMutex_);
if (!objects_.empty())
{
lastModified_ = objects_.crbegin()->second.lastModified_;
}
if (objects_.size() >= 2)
{
auto it = objects_.crbegin();
auto lastModified = it->second.lastModified_;
auto prevModified = (++it)->second.lastModified_;
auto delta = lastModified - prevModified;
updatePeriod_ = std::chrono::duration_cast<std::chrono::seconds>(delta);
}
}
std::chrono::system_clock::time_point
AwsLevel2DataProvider::GetTimePointByKey(const std::string& key) const
{
return GetTimePointFromKey(key);
}
std::chrono::system_clock::time_point std::chrono::system_clock::time_point
AwsLevel2DataProvider::GetTimePointFromKey(const std::string& key) AwsLevel2DataProvider::GetTimePointFromKey(const std::string& key)
{ {