Stroika Library 3.0d20
 
Loading...
Searching...
No Matches
MongoDBClient.h
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Database_Document_MongoDBClient_h_
5#define _Stroika_Foundation_Database_Document_MongoDBClient_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#if qStroika_HasComponent_mongocxxdriver
10// forward declare so we can expose these interfaces to code which #includes the appropriate file, but not force
11// its inclusion just to use the MongoDBClient
12namespace mongocxx::v_noabi {
13 class client;
14 class pool;
15 class instance;
16}
17namespace mongocxx {
18 using ::mongocxx::v_noabi::client;
19 using ::mongocxx::v_noabi::instance;
20 using ::mongocxx::v_noabi::pool;
21}
22#endif
23
28
29/*
30 * \file
31 *
32 * \note Code-Status: <a href="Code-Status.md#Alpha">Alpha</a>
33 *
34 * TODO:
35 *
36 */
37
38/*
39@CONFIGVAR: DqStroika_HasComponent_mongocxxdriver
40@DESCRIPTION: Defines if Stroika is built supporting mongo-cxx-driver
41*/
42#ifndef qStroika_HasComponent_mongocxxdriver
43#error "qStroika_HasComponent_mongocxxdriver should normally be defined indirectly by StroikaConfig.h"
44#endif
45
46namespace Stroika::Foundation::Database::Document::MongoDBClient {
47
48#if qStroika_HasComponent_mongocxxdriver
49
50 /**
51 * \brief must be instantiated after main, but before any use of MongoCXX library methods, and destroyed after all such methods
52 *
53 * \pre Debug::AppearsDuringMainLifetime ()
54 *
55 * From mongo-cxx-driver source code:
56 * Exactly one instance must be created in a given program. Not constructing an instance or
57 * constructing more than one instance in a program are errors, even if the multiple instances have
58 * non-overlapping lifetimes.
59 *
60 * To allow Stroika code to activate and deactivate (rarely but possibly useful) - an optional flag is provided, and
61 * if set allowReactivation=true, then the underlying mongocxx instance object not destroyed until application end,
62 * so that you can re-activate. JUST IGNORE this for hte most part and stick with the default!
63 */
64 struct Activator final {
65 enum AllowReactivateFlag {
66 eAllowReactivateFlag
67 };
68 Activator ();
69 Activator (AllowReactivateFlag);
70 ~Activator ();
71
72 private:
73 bool fAllowReactivation_;
74 static unique_ptr<mongocxx::instance> sMongoInstance_;
75 };
76
77 /**
78 * \brief optionally pool mongodb connections (to a given server). Create the object and pass it
79 * as 'target' option to Connection::New()...
80 *
81 * \note \em Thread-Safety <a href="Thread-Safety.md#Internally-Synchronized-Thread-Safety">Internally-Synchronized-Thread-Safety</a>
82 */
83 class ConnectionPool final {
84 public:
85 ConnectionPool () = delete;
86 ConnectionPool (const ConnectionPool&) = default;
87 ConnectionPool (shared_ptr<mongocxx::pool>&& poolRep);
88 ConnectionPool (const String& connectionString);
89 ~ConnectionPool () = default;
90
91 public:
92 /**
93 */
94 nonvirtual mongocxx::pool& PeekPool () const;
95
96 private:
97 // shared_ptr is internally synchronized for copies / control block updates (refCnt) - and mongocxx::pool internally syncrhonized
98 shared_ptr<mongocxx::pool> fPool_;
99 };
100
101 namespace AdminConnection {
102 class IRep;
103
104 /**
105 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
106 */
107 class Ptr : public shared_ptr<IRep> {
108 private:
109 using inherited = shared_ptr<IRep>;
110
111 public:
112 /**
113 */
114 Ptr (const Ptr& src) noexcept = default;
115 Ptr (const shared_ptr<IRep>& src = nullptr) noexcept;
116
117 public:
118 ~Ptr () noexcept = default;
119
120 public:
121 /**
122 */
123 nonvirtual Document run_command (const Document& v);
124
125 public:
126 /**
127 */
128 nonvirtual mongocxx::client& GetClientRef ();
129
130 public:
131 /**
132 */
133 nonvirtual Set<String> GetDatabases ();
134
135 public:
136 /**
137 */
138 nonvirtual void DropDatabase (const String& dbName);
139
140 public:
141 /**
142 */
143 nonvirtual void CreateDatabase (const String& dbName);
144 };
145
146 /**
147 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
148 */
149 class IRep {
150 public:
151 virtual Document run_command (const Document& v) = 0;
152
153 public:
154 virtual mongocxx::client& GetClientRef () = 0;
155
156 public:
157 virtual Set<String> GetDatabases () = 0;
158
159 public:
160 virtual void DropDatabase (const String& dbName) = 0;
161
162 public:
163 virtual void CreateDatabase (const String& dbName) = 0;
164 };
165
166 /**
167 * These are options used to create a database Connection::Ptr object (with Connection::New).
168 *
169 * Since this is also how you create a database, in a sense, its those options too.
170 */
171 struct Options final {
172 /**
173 * @brief see https://www.mongodb.com/docs/manual/reference/connection-string/
174 */
175 variant<String, ConnectionPool> fConnectionTarget;
176 };
177
178 /**
179 * \note produces unsynchronized reps - so must be externally synchronized
180 */
181 Ptr New (const Options& options);
182 }
183
184 namespace Connection {
185
186 using namespace Database::Document::Connection;
187
188 class IRep;
189
190 /**
191 * These are options used to create a database Connection::Ptr object (with Connection::New).
192 *
193 * Since this is also how you create a database, in a sense, its those options too.
194 */
195 struct Options final {
196 /**
197 * @brief see https://www.mongodb.com/docs/manual/reference/connection-string/
198 */
199 variant<String, ConnectionPool> fConnectionTarget;
200
201 /**
202 * Connection string does not contain database name. Different from Mongo API, we choose to require a database name
203 * in the connection options. Use AdminConnection to operate on server itself, not a particular database.
204 */
205 String fDatabase;
206 };
207
208 /**
209 * Connection provides an API for accessing a particular MongoDB database.
210 *
211 * A new Connection::Ptr is typically created MongoDBClient::Connection::New()
212 */
213 class Ptr : public Database::Document::Connection::Ptr {
214 private:
215 using inherited = Database::Document::Connection::Ptr;
216
217 public:
218 /**
219 */
220 Ptr (const Ptr& src);
221 Ptr (const shared_ptr<IRep>& src = nullptr);
222
223 public:
224 ~Ptr () = default;
225
226 public:
227 /**
228 */
229 nonvirtual Ptr& operator= (const Ptr& src);
230 nonvirtual Ptr& operator= (Ptr&& src) noexcept;
231
232 public:
233 /**
234 */
235 nonvirtual IRep* operator->() const noexcept;
236
237 public:
238 /**
239 */
240 nonvirtual mongocxx::client& GetClientRef ();
241 };
242
243 /**
244 * \note produces unsynchronized reps - so must be externally synchronized
245 */
246 Ptr New (const Options& options);
247
248 /**
249 * Connection provides an API for accessing an MongoDBClient database.
250 *
251 * Typically don't use this directly, but use Connection::Ptr, a smart ptr wrapper on this interface.
252 */
253 class IRep : public Database::Document::Connection::IRep {
254 public:
255 virtual mongocxx::client& GetClientRef () = 0;
256 };
257
258 };
259
260 /**
261 * @todo NYI
262 */
263 class Transaction : public Database::Document::Transaction {
264 private:
265 using inherited = Database::Document::Transaction;
266
267 public:
268 /**
269 */
270 Transaction () = delete;
271 Transaction (const Connection::Ptr& db);
272 Transaction (const Transaction&) = delete;
273
274 private:
275 struct MyRep_;
276 };
277#endif
278
279}
280
281/*
282 ********************************************************************************
283 ***************************** Implementation Details ***************************
284 ********************************************************************************
285 */
286#include "MongoDBClient.inl"
287
288#endif /*_Stroika_Foundation_Database_Document_MongoDBClient_h_*/
Mapping< String, VariantValue > Document
Definition Document.h:28