Skip to content

Commit

Permalink
Add async methods for GetLatestVersion
Browse files Browse the repository at this point in the history
Creation of asynchronous methods is a part of task
continuation changes, later will be used in asynchronous
GetVersion method. GetVersion is not added in this commit
as it's in the private section and cannot be covered with tests.

Add asynchronous version of GetLatestVersion method
which handles the logic of getting data from cache/network.
Add asynchronous version of GetLatestCatalogVersion.
Move common functionality of getting data from the cache
and storing data returned from a request to the cache
to the RetrieveLatestVersion function.

Add unit tests which cover asynchronous methods for getting
the latest version.
Replaced mock expectation arguments with WithoutArgs.

Relates-To: OLPEDGE-2718

Signed-off-by: Yevhenii Dudnyk <ext-yevhenii.dudnyk@here.com>
  • Loading branch information
dudnyk committed Feb 7, 2022
1 parent b1cd55b commit 20d7ec1
Show file tree
Hide file tree
Showing 5 changed files with 596 additions and 275 deletions.
34 changes: 31 additions & 3 deletions olp-cpp-sdk-dataservice-read/src/generated/api/MetadataApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ MetadataApi::PartitionsExtendedResponse MetadataApi::GetPartitions(
auto partitions_response =
parser::parse_result<PartitionsResponse>(http_response.response);

if (!partitions_response.IsSuccessful()) {
if (!partitions_response) {
return {{partitions_response.GetError()},
http_response.GetNetworkStatistics()};
}
Expand All @@ -134,14 +134,14 @@ MetadataApi::PartitionsExtendedResponse MetadataApi::GetPartitions(
}

MetadataApi::CatalogVersionResponse MetadataApi::GetLatestCatalogVersion(
const client::OlpClient& client, std::int64_t startVersion,
const client::OlpClient& client, std::int64_t start_version,
boost::optional<std::string> billing_tag,
const client::CancellationContext& context) {
std::multimap<std::string, std::string> header_params;
header_params.emplace("Accept", "application/json");

std::multimap<std::string, std::string> query_params;
query_params.emplace("startVersion", std::to_string(startVersion));
query_params.emplace("startVersion", std::to_string(start_version));
if (billing_tag) {
query_params.emplace("billingTag", *billing_tag);
}
Expand All @@ -158,6 +158,34 @@ MetadataApi::CatalogVersionResponse MetadataApi::GetLatestCatalogVersion(
return parser::parse_result<CatalogVersionResponse>(api_response.response);
}

client::CancellationToken MetadataApi::GetLatestCatalogVersion(
const client::OlpClient& client, int64_t start_version,
boost::optional<std::string> billing_tag, CatalogVersionCallback callback) {
std::multimap<std::string, std::string> header_params;
header_params.emplace("Accept", "application/json");

std::multimap<std::string, std::string> query_params;
query_params.emplace("startVersion", std::to_string(start_version));
if (billing_tag) {
query_params.emplace("billingTag", *billing_tag);
}

std::string metadata_uri = "/versions/latest";

return client.CallApi(
metadata_uri, "GET", query_params, header_params, {}, nullptr, "",
[callback](client::HttpResponse api_response) {
if (api_response.status != http::HttpStatusCode::OK) {
callback(client::ApiError(api_response.status,
api_response.response.str()));
return;
}

callback(parser::parse_result<CatalogVersionResponse>(
api_response.response));
});
}

MetadataApi::VersionsResponse MetadataApi::ListVersions(
const client::OlpClient& client, std::int64_t start_version,
std::int64_t end_version, boost::optional<std::string> billing_tag,
Expand Down
21 changes: 21 additions & 0 deletions olp-cpp-sdk-dataservice-read/src/generated/api/MetadataApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <boost/optional.hpp>
#include "ExtendedApiResponse.h"
#include "generated/model/LayerVersions.h"
#include "olp/dataservice/read/Types.h"
#include "olp/dataservice/read/model/Partitions.h"
#include "olp/dataservice/read/model/VersionInfos.h"
#include "olp/dataservice/read/model/VersionResponse.h"
Expand Down Expand Up @@ -130,6 +131,26 @@ class MetadataApi {
boost::optional<std::string> billing_tag,
const client::CancellationContext& context);

/**
* @brief Retrieves the latest metadata version for the catalog.
*
* @param client Instance of OlpClient used to make REST request.
* @param start_version The catalog version returned from a prior request.
* Save the version from each request so it can used in the startVersion
* parameter of subsequent requests. If the version from a prior request is
* not avaliable, set the parameter to -1.
* @param billing_tag An optional free-form tag which is used for grouping
* billing records together. If supplied, it must be between 4 - 16
* characters, contain only alpha/numeric ASCII characters [A-Za-z0-9].
* @param callback The callback which returns a result of the operation.
*
* @return The `CancellationToken` instance.
*/
static client::CancellationToken GetLatestCatalogVersion(
const client::OlpClient& client, int64_t start_version,
boost::optional<std::string> billing_tag,
read::CatalogVersionCallback callback);

static VersionsResponse ListVersions(
const client::OlpClient& client, int64_t start_version,
int64_t end_version, boost::optional<std::string> billing_tag,
Expand Down
159 changes: 140 additions & 19 deletions olp-cpp-sdk-dataservice-read/src/repositories/CatalogRepository.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,64 @@
#include "olp/dataservice/read/VersionsRequest.h"

namespace {
constexpr auto kDefaultStartVersion = 0;
constexpr auto kLogTag = "CatalogRepository";

// The function retrieves the maximum version among cached/online/user-provided
// versions.
// Update the cache, if the retrieved version is greater than the cached one.
olp::dataservice::read::CatalogVersionResponse RetrieveLatestVersion(
const olp::client::HRN& catalog,
const olp::dataservice::read::CatalogVersionRequest& request,
olp::dataservice::read::repository::CatalogCacheRepository& repository,
olp::dataservice::read::CatalogVersionResponse&& version_response) {
auto cached_version = repository.GetVersion();
auto fetch_option = request.GetFetchOption();

// Using `GetStartVersion` to set up a new latest version for CacheOnly
// requests in case of absence of the previous latest version or it's less
// than the new user set version.
if (fetch_option == olp::dataservice::read::FetchOptions::CacheOnly) {
const auto start_version = request.GetStartVersion();
if (start_version >= kDefaultStartVersion &&
(!cached_version || start_version > cached_version->GetVersion())) {
olp::dataservice::read::model::VersionResponse new_response;
new_response.SetVersion(start_version);
version_response = std::move(new_response);
}
}

if (version_response) {
const auto new_version = version_response.GetResult().GetVersion();

// Write or update a version in the cache, updating happens only when the
// new version is greater than cached.
if (!cached_version || cached_version->GetVersion() < new_version) {
repository.PutVersion(version_response.GetResult());
if (fetch_option == olp::dataservice::read::FetchOptions::CacheOnly) {
OLP_SDK_LOG_DEBUG_F(
kLogTag, "Latest user set version, hrn='%s', version=%" PRId64,
catalog.ToCatalogHRNString().c_str(), new_version);
} else {
OLP_SDK_LOG_DEBUG_F(kLogTag,
"Latest online version, hrn='%s', version=%" PRId64,
catalog.ToCatalogHRNString().c_str(), new_version);
}
}

return std::move(version_response);
}

if (cached_version) {
OLP_SDK_LOG_DEBUG_F(
kLogTag, "Latest cached version, hrn='%s', version=%" PRId64,
catalog.ToCatalogHRNString().c_str(), cached_version->GetVersion());
version_response = std::move(*cached_version);
}

return std::move(version_response);
}

} // namespace

namespace olp {
Expand All @@ -56,8 +113,8 @@ CatalogResponse CatalogRepository::GetCatalog(
const auto fetch_options = request.GetFetchOption();
const auto catalog_str = catalog_.ToCatalogHRNString();

repository::CatalogCacheRepository repository(
catalog_, settings_.cache, settings_.default_cache_expiration);
CatalogCacheRepository repository(catalog_, settings_.cache,
settings_.default_cache_expiration);

if (fetch_options != OnlineOnly && fetch_options != CacheWithUpdate) {
auto cached = repository.Get();
Expand All @@ -80,18 +137,19 @@ CatalogResponse CatalogRepository::GetCatalog(
"config", "v1", static_cast<client::FetchOptions>(fetch_options),
context);

if (!config_api.IsSuccessful()) {
if (!config_api) {
return config_api.GetError();
}

const client::OlpClient& config_client = config_api.GetResult();
auto catalog_response = ConfigApi::GetCatalog(
config_client, catalog_str, request.GetBillingTag(), context);

if (catalog_response.IsSuccessful() && fetch_options != OnlineOnly) {
if (catalog_response && fetch_options != OnlineOnly) {
repository.Put(catalog_response.GetResult());
}
if (!catalog_response.IsSuccessful()) {

if (!catalog_response) {
const auto& error = catalog_response.GetError();
if (error.GetHttpStatusCode() == http::HttpStatusCode::FORBIDDEN) {
OLP_SDK_LOG_WARNING_F(kLogTag,
Expand All @@ -107,12 +165,12 @@ CatalogResponse CatalogRepository::GetCatalog(

CatalogVersionResponse CatalogRepository::GetLatestVersion(
const CatalogVersionRequest& request, client::CancellationContext context) {
repository::CatalogCacheRepository repository(
catalog_, settings_.cache, settings_.default_cache_expiration);
CatalogCacheRepository repository(catalog_, settings_.cache,
settings_.default_cache_expiration);

const auto fetch_option = request.GetFetchOption();
// in case get version online was never called and version was not found in
// cache
// In case `GetVersionOnline` was never called and version was not found in
// the cache
CatalogVersionResponse version_response = {
{client::ErrorCode::NotFound, "Failed to find version."}};

Expand All @@ -124,7 +182,7 @@ CatalogVersionResponse CatalogRepository::GetLatestVersion(
return version_response;
}

if (!version_response.IsSuccessful()) {
if (!version_response) {
const auto& error = version_response.GetError();
if (error.GetHttpStatusCode() == http::HttpStatusCode::FORBIDDEN) {
OLP_SDK_LOG_WARNING_F(
Expand All @@ -143,8 +201,6 @@ CatalogVersionResponse CatalogRepository::GetLatestVersion(
// requests in case of absence of previous latest version or it less than the
// new user set version
if (fetch_option == CacheOnly) {
constexpr auto kDefaultStartVersion = 0;

auto user_set_version = request.GetStartVersion();
if (user_set_version >= kDefaultStartVersion) {
if (!cached_version || user_set_version > cached_version->GetVersion()) {
Expand All @@ -155,11 +211,11 @@ CatalogVersionResponse CatalogRepository::GetLatestVersion(
}
}

if (version_response.IsSuccessful()) {
if (version_response) {
const auto new_version = version_response.GetResult().GetVersion();
// Write or update the version in cache, updating happens only when the new
// version is greater than cached.
if (!cached_version || (*cached_version).GetVersion() < new_version) {
if (!cached_version || cached_version->GetVersion() < new_version) {
repository.PutVersion(version_response.GetResult());
if (fetch_option == CacheOnly) {
OLP_SDK_LOG_DEBUG_F(
Expand All @@ -171,25 +227,69 @@ CatalogVersionResponse CatalogRepository::GetLatestVersion(
catalog_.ToCatalogHRNString().c_str(), new_version);
}
}

return version_response;
}

if (cached_version) {
OLP_SDK_LOG_DEBUG_F(
kLogTag, "Latest cached version, hrn='%s', version=%" PRId64,
catalog_.ToCatalogHRNString().c_str(), (*cached_version).GetVersion());
version_response = *std::move(cached_version);
catalog_.ToCatalogHRNString().c_str(), cached_version->GetVersion());
version_response = std::move(*cached_version);
}

return version_response;
}

client::CancellationToken CatalogRepository::GetLatestVersion(
const CatalogVersionRequest& request, CatalogVersionCallback callback) {
CatalogCacheRepository repository(catalog_, settings_.cache,
settings_.default_cache_expiration);

const auto fetch_option = request.GetFetchOption();

if (fetch_option == CacheOnly) {
// Initialize response to an error. It will be overwritten in case a valid
// version is found in the cache or user request.
CatalogVersionResponse version_response{
{client::ErrorCode::NotFound, "Failed to find a catalog version."}};

callback(RetrieveLatestVersion(catalog_, request, repository,
std::move(version_response)));
return client::CancellationToken();
}

return GetLatestVersionOnline(
request.GetBillingTag(), [=](CatalogVersionResponse response) mutable {
if (fetch_option == OnlineOnly) {
callback(std::move(response));
return;
}

if (!response) {
const auto& error = response.GetError();
if (error.GetHttpStatusCode() == http::HttpStatusCode::FORBIDDEN) {
OLP_SDK_LOG_WARNING_F(
kLogTag,
"Latest version request ended with 403 HTTP code, hrn='%s'",
catalog_.ToCatalogHRNString().c_str());
repository.Clear();
callback(std::move(response));
return;
}
}

callback(RetrieveLatestVersion(catalog_, request, repository,
std::move(response)));
});
}

VersionsResponse CatalogRepository::GetVersionsList(
const VersionsRequest& request, client::CancellationContext context) {
auto metadata_api =
lookup_client_.LookupApi("metadata", "v1", client::OnlineOnly, context);

if (!metadata_api.IsSuccessful()) {
if (!metadata_api) {
return metadata_api.GetError();
}

Expand All @@ -206,7 +306,7 @@ CatalogVersionResponse CatalogRepository::GetLatestVersionOnline(
auto metadata_api = lookup_client_.LookupApi(
"metadata", "v1", client::OnlineIfNotFound, context);

if (!metadata_api.IsSuccessful()) {
if (!metadata_api) {
return metadata_api.GetError();
}

Expand All @@ -216,13 +316,34 @@ CatalogVersionResponse CatalogRepository::GetLatestVersionOnline(
context);
}

client::CancellationToken CatalogRepository::GetLatestVersionOnline(
const boost::optional<std::string>& billing_tag,
CatalogVersionCallback callback) {
return lookup_client_.LookupApi(
"metadata", "v1", client::OnlineIfNotFound,
[=](client::ApiLookupClient::LookupApiResponse response) {
if (!response) {
callback(response.GetError());
return client::CancellationToken();
}

const auto& metadata_client = response.GetResult();

return MetadataApi::GetLatestCatalogVersion(
metadata_client, -1, billing_tag,
[=](CatalogVersionResponse catalog_version_response) {
callback(std::move(catalog_version_response));
});
});
}

CompatibleVersionsResponse CatalogRepository::GetCompatibleVersions(
const CompatibleVersionsRequest& request,
client::CancellationContext context) {
auto metadata_api =
lookup_client_.LookupApi("metadata", "v1", client::OnlineOnly, context);

if (!metadata_api.IsSuccessful()) {
if (!metadata_api) {
return metadata_api.GetError();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2020 HERE Europe B.V.
* Copyright (C) 2019-2022 HERE Europe B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -49,6 +49,9 @@ class CatalogRepository final {
CatalogVersionResponse GetLatestVersion(const CatalogVersionRequest& request,
client::CancellationContext context);

client::CancellationToken GetLatestVersion(
const CatalogVersionRequest& request, CatalogVersionCallback callback);

VersionsResponse GetVersionsList(const VersionsRequest& request,
client::CancellationContext context);

Expand All @@ -61,6 +64,10 @@ class CatalogRepository final {
const boost::optional<std::string>& billing_tag,
client::CancellationContext context);

client::CancellationToken GetLatestVersionOnline(
const boost::optional<std::string>& billing_tag,
CatalogVersionCallback callback);

client::HRN catalog_;
client::OlpClientSettings settings_;
client::ApiLookupClient lookup_client_;
Expand Down
Loading

0 comments on commit 20d7ec1

Please sign in to comment.