userver: userver/cache/mongo_cache_type_traits.hpp Source File
Loading...
Searching...
No Matches
mongo_cache_type_traits.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/cache/mongo_cache_type_traits.hpp
4/// @brief Compile-time concepts and static checks for BaseMongoCache traits
5
6#include <chrono>
7#include <type_traits>
8
9#include <userver/cache/update_type.hpp>
10#include <userver/utils/meta.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace formats::bson {
15class Document;
16}
17
18namespace storages::mongo::operations {
19class Find;
20}
21
22namespace mongo_cache::impl {
23
24template <typename T>
25concept HasCollectionsField = requires { T::kMongoCollectionsField; };
26
27template <typename T>
28concept HasUpdateFieldName = requires { T::kMongoUpdateFieldName; };
29
30template <typename T>
31concept HasKeyField = requires { T::kKeyField; };
32
33template <typename T>
34concept HasValidDataType = meta::kIsMap<typename T::DataType>;
35
36template <typename T>
37concept HasSecondaryPreferred = requires { T::kIsSecondaryPreferred; };
38
39template <typename T>
40concept HasDeserializeObject = requires { T::DeserializeObject; };
41
42template <typename T>
43concept HasCorrectDeserializeObject = requires(const T& t, const formats::bson::Document& doc) {
44 {
45 t.DeserializeObject(doc)
46 } -> std::same_as<typename T::ObjectType>;
47};
48
49template <typename T>
50concept HasDefaultDeserializeObject = requires { T::kUseDefaultDeserializeObject; };
51
52template <typename T>
53concept HasFindOperation = requires { T::GetFindOperation; };
54
55template <typename T>
56concept HasCorrectFindOperation = requires(
57 const T& t,
58 cache::UpdateType update_type,
59 const std::chrono::system_clock::time_point& last_update,
60 const std::chrono::system_clock::time_point& now,
61 const std::chrono::system_clock::duration& correction
62) {
63 // NOLINTNEXTLINE(readability-static-accessed-through-instance)
64 {
65 t.GetFindOperation(update_type, last_update, now, correction)
66 } -> std::same_as<storages::mongo::operations::Find>;
67};
68
69template <typename T>
70concept HasDefaultFindOperation = requires { T::kUseDefaultFindOperation; };
71
72/// @brief Whether the traits define the query themselves.
73///
74/// If they don't, the query is only known at runtime, and
75/// components::MongoCache::MakeFindOperation is pure virtual, so the compiler
76/// requires a derived component to build the query.
77template <typename T>
78concept HasFindOperationInTraits = HasFindOperation<T> || HasDefaultFindOperation<T>;
79
80template <typename T>
81concept HasInvalidDocumentsSkipped = requires { T::kAreInvalidDocumentsSkipped; };
82
83template <typename>
84struct ClassByMemberPointer {};
85template <typename T, typename C>
86struct ClassByMemberPointer<T C::*> {
87 using type = C;
88};
89template <typename CollectionPtr>
90using CollectionsType = typename ClassByMemberPointer<std::remove_cv_t<CollectionPtr>>::type;
91
92template <typename MongoCacheTraits>
93struct CheckTraits {
94 CheckTraits() {
95 if constexpr (HasDefaultDeserializeObject<MongoCacheTraits>) {
96 static_assert(
97 std::is_same_v<std::decay_t<decltype(MongoCacheTraits::kUseDefaultDeserializeObject)>, bool>,
98 "Mongo cache traits must specify kUseDefaultDeserializeObject as "
99 "bool"
100 );
101 }
102 if constexpr (HasDefaultFindOperation<MongoCacheTraits>) {
103 static_assert(
104 std::is_same_v<std::decay_t<decltype(MongoCacheTraits::kUseDefaultFindOperation)>, bool>,
105 "Mongo cache traits must specify kUseDefaultFindOperation as bool"
106 );
107 }
108 }
109
110 static_assert(HasCollectionsField<MongoCacheTraits>, "Mongo cache traits must specify collections field");
111 static_assert(HasKeyField<MongoCacheTraits>, "Mongo cache traits must specify key field");
112 static_assert(HasValidDataType<MongoCacheTraits>, "Mongo cache traits must specify mapping data type");
113
114 static_assert(HasSecondaryPreferred<MongoCacheTraits>, "Mongo cache traits must specify read preference");
115 static_assert(
116 std::is_same_v<std::decay_t<decltype(MongoCacheTraits::kIsSecondaryPreferred)>, bool>,
117 "Mongo cache traits must specify read preference of a bool type"
118 );
119
120 static_assert(HasInvalidDocumentsSkipped<MongoCacheTraits>, "Mongo cache traits must specify validation policy");
121 static_assert(
122 std::is_same_v<std::decay_t<decltype(MongoCacheTraits::kAreInvalidDocumentsSkipped)>, bool>,
123 "Mongo cache traits must specify validation policy of a bool type"
124 );
125
126 static_assert(
127 !HasFindOperation<MongoCacheTraits> || HasCorrectFindOperation<MongoCacheTraits>,
128 "Mongo cache traits must specify find operation with correct "
129 "signature and return value type: "
130 "static storages::mongo::operations::Find GetFindOperation("
131 "cache::UpdateType type, "
132 "const std::chrono::system_clock::time_point& last_update, "
133 "const std::chrono::system_clock::time_point& now, "
134 "const std::chrono::system_clock::duration& correction)"
135 );
136
137 static_assert(
138 HasDeserializeObject<MongoCacheTraits> || HasDefaultDeserializeObject<MongoCacheTraits>,
139 "Mongo cache traits must specify deserialize object"
140 );
141 static_assert(
142 !HasDeserializeObject<MongoCacheTraits> || HasCorrectDeserializeObject<MongoCacheTraits>,
143 "Mongo cache traits must specify deserialize object with correct "
144 "signature and return value type: "
145 "static ObjectType DeserializeObject(const formats::bson::Document& "
146 "doc)"
147 );
148};
149
150} // namespace mongo_cache::impl
151
152USERVER_NAMESPACE_END