libkazv
Loading...
Searching...
No Matches
sdk.hpp
Go to the documentation of this file.
1/*
2 * This file is part of libkazv.
3 * SPDX-FileCopyrightText: 2020-2021 Tusooa Zhu <tusooa@kazv.moe>
4 * SPDX-License-Identifier: AGPL-3.0-or-later
5 */
6
7#pragma once
8#include <libkazv-config.hpp>
9#include <lager/store.hpp>
10
11#include <random>
12
13#include <store.hpp>
14
15#include "sdk-model.hpp"
17#include "client.hpp"
19
20#include "random-generator.hpp"
21
22
23namespace Kazv
24{
28 template<class EventLoop, class Xform, class ...Enhancers>
29 class Sdk
30 {
33 using ActionT = typename ModelT::Action;
34 using CursorT = lager::reader<ModelT>;
35 using CursorTSP = std::shared_ptr<CursorT>;
36
37 using StoreT = decltype(
38 makeStore<ActionT>(
39 std::declval<ModelT>(),
41 std::declval<EventLoop>(),
42 lager::with_deps(
43 std::ref(detail::declref<JobInterface>()),
44 std::ref(detail::declref<EventInterface>()),
45 lager::dep::as<SdkModelCursorKey>(std::declval<std::function<CursorTSP()>>()),
46 std::ref(detail::declref<RandomInterface>())
47#ifdef KAZV_USE_THREAD_SAFETY_HELPER
48 , std::ref(detail::declref<EventLoopThreadIdKeeper>())
49#endif
50 ),
51 std::declval<Enhancers>()...)
52 );
53
54 using DepsT = lager::deps<JobInterface &, EventInterface &, SdkModelCursorKey, RandomInterface &
55#ifdef KAZV_USE_THREAD_SAFETY_HELPER
56 , EventLoopThreadIdKeeper &
57#endif
58 >;
59
61 public:
62 Sdk(ModelT model,
63 JobInterface &jobHandler,
64 EventInterface &eventEmitter,
65 EventLoop &&eventLoop,
66 Xform &&xform,
67 Enhancers &&...enhancers)
68 : m_d(std::make_unique<Private>(
69 std::move(model), jobHandler, eventEmitter,
70 std::forward<EventLoop>(eventLoop), std::forward<Xform>(xform),
71 std::forward<Enhancers>(enhancers)...)) {}
72
79 ContextT context() const {
80 return m_d->store;
81 }
82
88 Client client() const {
89 return {Client::InEventLoopTag{}, ContextT(m_d->store)};
90 }
91
102 template<class EL>
103 auto createSecondaryRoot(EL &&eventLoop, ModelT initialModel = ModelT{}) const {
104 auto secondaryStore = lager::make_store<ModelT>(
105 std::move(initialModel),
106 std::forward<EL>(eventLoop),
107 lager::with_reducer([](auto &&, auto next) { return next; }));
108
109 lager::context<ModelT> secondaryCtx = secondaryStore;
110
112 .then([secondaryCtx, d=m_d.get()](auto &&) {
113 lager::watch(*(d->sdk),
114 [secondaryCtx](auto next) { secondaryCtx.dispatch(std::move(next)); });
115 });
116
117 return secondaryStore;
118 }
119
132 Client clientFromSecondaryRoot(lager::reader<ModelT> sr) const {
133 return Client(sr, ContextT(m_d->store));
134 }
135
136 private:
137 struct Private
138 {
139 Private(ModelT model,
140 JobInterface &jobHandler,
141 EventInterface &eventEmitter,
142 EventLoop &&eventLoop,
143 Xform &&xform,
144 Enhancers &&...enhancers)
146 , store(makeStore<ActionT>(
147 std::move(model),
148 &ModelT::update,
149 std::forward<EventLoop>(eventLoop),
150 lager::with_deps(
151 std::ref(jobHandler),
152 std::ref(eventEmitter),
153 lager::dep::as<SdkModelCursorKey>(
154 std::function<CursorTSP()>([this] { return sdk; })),
155 std::ref(rg.value())
156#ifdef KAZV_USE_THREAD_SAFETY_HELPER
157 , std::ref(keeper)
158#endif
159 ),
160 std::forward<Enhancers>(enhancers)...))
161 , sdk(std::make_shared<lager::reader<ModelT>>(store.reader().xform(std::forward<Xform>(xform))))
162 {
163#ifdef KAZV_USE_THREAD_SAFETY_HELPER
164 store.context().createResolvedPromise(EffectStatus{})
165 .then([this](auto &&) {
166 keeper.set(std::this_thread::get_id());
167 });
168#endif
169 }
170#ifdef KAZV_USE_THREAD_SAFETY_HELPER
171 EventLoopThreadIdKeeper keeper;
172#endif
173 std::optional<RandomInterface> rg;
174 StoreT store;
175 CursorTSP sdk;
176 };
177
178 std::unique_ptr<Private> m_d;
179 };
180
199 template<class EventLoop, class Xform, class ...Enhancers>
200 inline auto makeSdk(SdkModel sdk,
201 JobInterface &jobHandler,
202 EventInterface &eventEmitter,
203 EventLoop &&eventLoop,
204 Xform &&xform,
205 Enhancers &&...enhancers)
206 -> Sdk<EventLoop, Xform, Enhancers...>
207 {
208 return { std::move(sdk),
209 jobHandler,
210 eventEmitter,
211 std::forward<EventLoop>(eventLoop),
212 std::forward<Xform>(xform),
213 std::forward<Enhancers>(enhancers)... };
214 }
215
220 {
221 return Crypto::constructRandomSize();
222 }
223
224 template<class EventLoop, class Xform, class ...Enhancers>
225 [[deprecated("Use deterministic makeDefaultSdkWithCryptoRandom instead. In the future, this will be removed.")]]
227 JobInterface &jobHandler,
228 EventInterface &eventEmitter,
229 EventLoop &&eventLoop,
230 Xform &&xform,
231 Enhancers &&...enhancers)
232 -> Sdk<EventLoop, Xform, Enhancers...>
233 {
234 auto m = SdkModel{};
236
237 return makeSdk(std::move(m),
238 jobHandler,
239 eventEmitter,
240 std::forward<EventLoop>(eventLoop),
241 std::forward<Xform>(xform),
242 std::forward<Enhancers>(enhancers)...);
243 }
244
265 template<class PH, class Xform, class ...Enhancers>
267 RandomData random,
268 JobInterface &jobHandler,
269 EventInterface &eventEmitter,
270 PH &&ph,
271 Xform &&xform,
272 Enhancers &&...enhancers)
273 -> Sdk<PH, Xform, Enhancers...>
274 {
275 auto m = SdkModel{};
276 m.client.crypto = Crypto(RandomTag{}, std::move(random));
277
278 return makeSdk(std::move(m),
279 jobHandler,
280 eventEmitter,
281 std::forward<PH>(ph),
282 std::forward<Xform>(xform),
283 std::forward<Enhancers>(enhancers)...);
284 }
285
286
295 {
296 return lager::with_deps(std::ref(random));
297 }
298}
Represent a Matrix client.
Definition client.hpp:60
Definition context.hpp:130
PromiseT createResolvedPromise(RetType v) const
Definition context.hpp:185
Definition crypto.hpp:36
Definition eventinterface.hpp:15
A movable wrapper around std::random_device.
Definition random-generator.hpp:103
Definition random-generator.hpp:16
Contain the single source of truth of a matrix sdk.
Definition sdk.hpp:30
Sdk(ModelT model, JobInterface &jobHandler, EventInterface &eventEmitter, EventLoop &&eventLoop, Xform &&xform, Enhancers &&...enhancers)
Definition sdk.hpp:62
ContextT context() const
Get the context associated with this.
Definition sdk.hpp:79
Client client() const
Get a Client representing this.
Definition sdk.hpp:88
auto createSecondaryRoot(EL &&eventLoop, ModelT initialModel=ModelT{}) const
Create a secondary root for this Sdk.
Definition sdk.hpp:103
Client clientFromSecondaryRoot(lager::reader< ModelT > sr) const
Get a Client representing this.
Definition sdk.hpp:132
Definition location.hpp:10
@ Private
Definition client-model.hpp:41
auto makeSdk(SdkModel sdk, JobInterface &jobHandler, EventInterface &eventEmitter, EventLoop &&eventLoop, Xform &&xform, Enhancers &&...enhancers) -> Sdk< EventLoop, Xform, Enhancers... >
Create an sdk with the provided model.
Definition sdk.hpp:200
lager::dep::key< SdkModelCursorTag, lager::dep::fn< std::shared_ptr< lager::reader< SdkModel > > > > SdkModelCursorKey
Definition sdk-model-cursor-tag.hpp:23
std::string RandomData
Definition crypto-util.hpp:35
RandomData genRandomData(int len)
Definition crypto-util.hpp:66
std::size_t makeDefaultSdkWithCryptoRandomSize()
Definition sdk.hpp:219
auto withRandomGenerator(RandomInterface &random)
An enhancer to use a custom random generator.
Definition sdk.hpp:294
auto makeDefaultSdkWithCryptoRandom(RandomData random, JobInterface &jobHandler, EventInterface &eventEmitter, PH &&ph, Xform &&xform, Enhancers &&...enhancers) -> Sdk< PH, Xform, Enhancers... >
Create an sdk with a default-constructed model, and a Crypto constructed with user-provided random da...
Definition sdk.hpp:266
auto makeDefaultEncryptedSdk(JobInterface &jobHandler, EventInterface &eventEmitter, EventLoop &&eventLoop, Xform &&xform, Enhancers &&...enhancers) -> Sdk< EventLoop, Xform, Enhancers... >
Definition sdk.hpp:226
auto makeStore(Model &&initialModel, Reducer &&reducer, PH &&ph, Enhancers &&...enhancers)
Definition store.hpp:141
Definition clientutil.hpp:140
Definition client-model.hpp:59
std::optional< immer::box< Crypto > > crypto
Definition client-model.hpp:85
Definition client.hpp:75
Definition jobinterface.hpp:21
The tag to indicate that a constructor should use user-provided random data.
Definition crypto-util.hpp:33
Definition sdk-model.hpp:26
SdkAction Action
Definition sdk-model.hpp:32
static SdkResult update(SdkModel s, SdkAction a)
Definition sdk-model.cpp:23
ClientModel client
Definition sdk-model.hpp:27