Store objects and get time point

This commit is contained in:
Dan Paulat 2022-04-30 21:07:44 -05:00
parent 1681b6772b
commit 690f3f6216
3 changed files with 93 additions and 3 deletions

View file

@ -27,5 +27,38 @@ TEST(AwsLevel2DataProvider, Refresh)
// TODO: Check object count // TODO: Check object count
} }
TEST(AwsLevel2DataProvider, TimePointValid)
{
using namespace std::chrono;
using sys_days = time_point<system_clock, days>;
constexpr auto expectedTime =
sys_days {2022y / April / 30d} + 17h + 27min + 34s;
auto time = AwsLevel2DataProvider::GetTimePointFromKey(
"2022/04/30/KLSX/KLSX20220430_172734_V06.gz");
EXPECT_EQ(time, expectedTime);
}
TEST(AwsLevel2DataProvider, TimePointInvalid)
{
constexpr std::chrono::system_clock::time_point expectedTime {};
auto time = AwsLevel2DataProvider::GetTimePointFromKey(
"2022/04/30/KLSX/KLSX20220430-172734_V06.gz");
EXPECT_EQ(time, expectedTime);
}
TEST(AwsLevel2DataProvider, TimePointBadKey)
{
constexpr std::chrono::system_clock::time_point expectedTime {};
auto time = AwsLevel2DataProvider::GetTimePointFromKey("???");
EXPECT_EQ(time, expectedTime);
}
} // namespace provider } // namespace provider
} // namespace scwx } // namespace scwx

View file

@ -32,6 +32,9 @@ public:
std::shared_ptr<wsr88d::Ar2vFile> LoadObjectByKey(const std::string& key); std::shared_ptr<wsr88d::Ar2vFile> LoadObjectByKey(const std::string& key);
void Refresh(); void Refresh();
static std::chrono::system_clock::time_point
GetTimePointFromKey(const std::string& key);
private: private:
std::unique_ptr<AwsLevel2DataProviderImpl> p; std::unique_ptr<AwsLevel2DataProviderImpl> p;
}; };

View file

@ -2,6 +2,8 @@
#include <scwx/util/logger.hpp> #include <scwx/util/logger.hpp>
#include <scwx/wsr88d/nexrad_file_factory.hpp> #include <scwx/wsr88d/nexrad_file_factory.hpp>
#include <shared_mutex>
#include <aws/s3/S3Client.h> #include <aws/s3/S3Client.h>
#include <aws/s3/model/GetObjectRequest.h> #include <aws/s3/model/GetObjectRequest.h>
#include <aws/s3/model/ListObjectsV2Request.h> #include <aws/s3/model/ListObjectsV2Request.h>
@ -15,7 +17,7 @@ namespace provider
static const std::string logPrefix_ = static const std::string logPrefix_ =
"scwx::provider::aws_level2_data_provider"; "scwx::provider::aws_level2_data_provider";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static const auto logger_ = util::Logger::Create(logPrefix_);
static const std::string kDefaultBucketName_ = "noaa-nexrad-level2"; static const std::string kDefaultBucketName_ = "noaa-nexrad-level2";
static const std::string kDefaultRegion_ = "us-east-1"; static const std::string kDefaultRegion_ = "us-east-1";
@ -29,7 +31,9 @@ public:
radarSite_ {radarSite}, radarSite_ {radarSite},
bucketName_ {bucketName}, bucketName_ {bucketName},
region_ {region}, region_ {region},
client_ {nullptr} client_ {nullptr},
objects_ {},
objectsMutex_ {}
{ {
Aws::Client::ClientConfiguration config; Aws::Client::ClientConfiguration config;
config.region = region_; config.region = region_;
@ -44,6 +48,9 @@ public:
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::shared_mutex objectsMutex_;
}; };
AwsLevel2DataProvider::AwsLevel2DataProvider(const std::string& radarSite) : AwsLevel2DataProvider::AwsLevel2DataProvider(const std::string& radarSite) :
@ -84,7 +91,19 @@ void AwsLevel2DataProvider::ListObjects(
logger_->debug("Found {} objects", objects.size()); logger_->debug("Found {} objects", objects.size());
// TODO: Store // Store objects
std::for_each(objects.cbegin(),
objects.cend(),
[&](const Aws::S3::Model::Object& object)
{
// TODO: Skip MDM
std::string key = object.GetKey();
auto time = GetTimePointFromKey(key);
std::unique_lock lock(p->objectsMutex_);
p->objects_[time] = key;
});
} }
else else
{ {
@ -130,5 +149,40 @@ void AwsLevel2DataProvider::Refresh()
ListObjects(std::chrono::system_clock::now()); ListObjects(std::chrono::system_clock::now());
} }
std::chrono::system_clock::time_point
AwsLevel2DataProvider::GetTimePointFromKey(const std::string& key)
{
std::chrono::system_clock::time_point time {};
const size_t lastSeparator = key.rfind('/');
const size_t offset =
(lastSeparator == std::string::npos) ? 0 : lastSeparator + 5;
// Filename format is GGGGYYYYMMDD_TTTTTT(_V##).gz
static constexpr size_t formatSize = std::string("YYYYMMDD_TTTTTT").size();
if (key.size() >= offset + formatSize)
{
using namespace std::chrono;
static const std::string timeFormat {"%Y%m%d_%H%M%S"};
std::string timeStr {key.substr(offset, formatSize)};
std::istringstream in {timeStr};
in >> parse(timeFormat, time);
if (in.fail())
{
logger_->warn("Invalid time: \"{}\"", timeStr);
}
}
else
{
logger_->warn("Time not parsable from key: \"{}\"", key);
}
return time;
}
} // namespace provider } // namespace provider
} // namespace scwx } // namespace scwx