A typical components::PostgreCache usage consists of trait definition:
struct PostgresTrivialPolicy {
static constexpr std::string_view kName = "my-pg-cache";
using ValueType = MyStructure;
static constexpr auto kKeyMember = &MyStructure::id;
static constexpr const char* kQuery = "SELECT a, b, updated FROM test.data";
static constexpr const char* kUpdatedField = "updated";
};
and registration of the component in components::ComponentList:
See Basics of Caches for introduction into caches.
Configuration
components::PostgreCache static configuration file should have a PostgreSQL component name specified in pgcomponent
configuration parameter.
Optionally the operation timeouts for cache loading can be specified.
Avoiding memory leaks
components::CachingComponentBase
Name | Description | Default value |
full-update-op-timeout | timeout for a full update | 1m |
incremental-update-op-timeout | timeout for an incremental update | 1s |
update-correction | incremental update window adjustment | - (0 for caches with defined GetLastKnownUpdated) |
chunk-size | number of rows to request from PostgreSQL via portals, 0 to fetch all rows in one request without portals | 1000 |
Cache policy
Cache policy is the template argument of components::PostgreCache component. Please see the following code snippet for documentation.
namespace example {
struct MyStructure {
int id = 0;
std::string bar{};
std::chrono::system_clock::time_point updated;
int get_id() const { return id; }
};
struct PostgresExamplePolicy {
static constexpr std::string_view kName = "my-pg-cache";
using ValueType = MyStructure;
static constexpr auto kKeyMember = &MyStructure::id;
static constexpr const char* kQuery =
"select id, bar, updated from test.my_data";
static constexpr const char* kUpdatedField = "updated";
static constexpr const char* kWhere = "id > 10";
using CacheContainer = std::unordered_map<int, MyStructure>;
static constexpr auto kClusterHostType =
static constexpr bool kMayReturnNull = false;
};
}
The query can be a std::string. But due to non-guaranteed order of static data members initialization, std::string should be returned from a static member function, please see the following code snippet.
struct PostgresExamplePolicy4 {
static constexpr std::string_view kName = "my-pg-cache";
using ValueType = MyStructure;
static constexpr auto kKeyMember = &MyStructure::id;
static std::string GetQuery() {
return "select id, bar, updated from test.my_data";
}
static constexpr const char* kUpdatedField = "updated";
using UpdatedFieldType =
};
Policy may have static function GetLastKnownUpdated. It should be used when new entries from database are taken via revision, identifier, or anything else, but not timestamp of the last update. If this function is supplied, new entries are taken from db with condition 'WHERE kUpdatedField > GetLastKnownUpdated(cache_container)'. Otherwise, condition is 'WHERE kUpdatedField > last_update - correction_'. See the following code snippet for an example of usage
struct MyStructureWithRevision {
int id = 0;
std::string bar{};
std::chrono::system_clock::time_point updated;
int32_t revision = 0;
int get_id() const { return id; }
};
class UserSpecificCache {
public:
void insert_or_assign(int, MyStructureWithRevision&& item) {
latest_revision_ = std::max(latest_revision_, item.revision);
}
static size_t size() { return 0; }
int GetLatestRevision() const { return latest_revision_; }
private:
int latest_revision_ = 0;
};
struct PostgresExamplePolicy3 {
using ValueType = MyStructureWithRevision;
static constexpr std::string_view kName = "my-pg-cache";
static constexpr const char* kQuery =
"select id, bar, revision from test.my_data";
using CacheContainer = UserSpecificCache;
static constexpr const char* kUpdatedField = "revision";
using UpdatedFieldType = int32_t;
static constexpr auto kKeyMember = &MyStructureWithRevision::get_id;
static int32_t GetLastKnownUpdated(const UserSpecificCache& container) {
return container.GetLatestRevision();
}
};
In case one provides a custom CacheContainer within Policy, it is notified of Update completion via its public member function OnWritesDone, if any. See the following code snippet for an example of usage:
class UserSpecificCacheWithWriteNotification {
public:
void insert_or_assign(int, MyStructure&&) {}
static size_t size() { return 0; }
void OnWritesDone() {}
};
Forward Declaration
To forward declare a cache you can forward declare a trait and include userver/cache/base_postgres_cache_fwd.hpp header. It is also useful to forward declare the cache value type.
#pragma once
#include <memory>
USERVER_NAMESPACE_BEGIN
namespace example {
struct PostgresExamplePolicy;
struct MyStructure;
}
namespace caches {
using MyCache1Data = std::shared_ptr<const example::MyStructure>;
}