1
- use std:: { fs , num:: NonZeroUsize , path :: Path , sync:: Arc , time:: Duration } ;
1
+ use std:: { num:: NonZeroUsize , sync:: Arc , time:: Duration } ;
2
2
3
3
use futures_util:: StreamExt ;
4
4
use matrix_sdk:: {
@@ -12,11 +12,10 @@ use matrix_sdk::{
12
12
VersionBuilderError ,
13
13
} ,
14
14
Client as MatrixClient , ClientBuildError as MatrixClientBuildError , HttpError , IdParseError ,
15
- RumaApiError , SqliteStoreConfig ,
15
+ RumaApiError ,
16
16
} ;
17
17
use ruma:: api:: error:: { DeserializationError , FromHttpResponseError } ;
18
18
use tracing:: { debug, error} ;
19
- use zeroize:: Zeroizing ;
20
19
21
20
use super :: client:: Client ;
22
21
use crate :: {
@@ -26,6 +25,7 @@ use crate::{
26
25
helpers:: unwrap_or_clone_arc,
27
26
qr_code:: { HumanQrLoginError , QrCodeData , QrLoginProgressListener } ,
28
27
runtime:: get_runtime_handle,
28
+ session_store:: { SessionStoreConfig , SessionStoreResult } ,
29
29
task_handle:: TaskHandle ,
30
30
} ;
31
31
@@ -108,11 +108,7 @@ impl From<ClientError> for ClientBuildError {
108
108
109
109
#[ derive( Clone , uniffi:: Object ) ]
110
110
pub struct ClientBuilder {
111
- session_paths : Option < SessionPaths > ,
112
- session_passphrase : Zeroizing < Option < String > > ,
113
- session_pool_max_size : Option < usize > ,
114
- session_cache_size : Option < u32 > ,
115
- session_journal_size_limit : Option < u32 > ,
111
+ session_store : Option < SessionStoreConfig > ,
116
112
system_is_memory_constrained : bool ,
117
113
username : Option < String > ,
118
114
homeserver_cfg : Option < HomeserverConfig > ,
@@ -138,11 +134,7 @@ impl ClientBuilder {
138
134
#[ uniffi:: constructor]
139
135
pub fn new ( ) -> Arc < Self > {
140
136
Arc :: new ( Self {
141
- session_paths : None ,
142
- session_passphrase : Zeroizing :: new ( None ) ,
143
- session_pool_max_size : None ,
144
- session_cache_size : None ,
145
- session_journal_size_limit : None ,
137
+ session_store : None ,
146
138
system_is_memory_constrained : false ,
147
139
username : None ,
148
140
homeserver_cfg : None ,
@@ -193,73 +185,6 @@ impl ClientBuilder {
193
185
Arc :: new ( builder)
194
186
}
195
187
196
- /// Sets the paths that the client will use to store its data and caches.
197
- /// Both paths **must** be unique per session as the SDK stores aren't
198
- /// capable of handling multiple users, however it is valid to use the
199
- /// same path for both stores on a single session.
200
- ///
201
- /// Leaving this unset tells the client to use an in-memory data store.
202
- pub fn session_paths ( self : Arc < Self > , data_path : String , cache_path : String ) -> Arc < Self > {
203
- let mut builder = unwrap_or_clone_arc ( self ) ;
204
- builder. session_paths = Some ( SessionPaths { data_path, cache_path } ) ;
205
- Arc :: new ( builder)
206
- }
207
-
208
- /// Set the passphrase for the stores given to
209
- /// [`ClientBuilder::session_paths`].
210
- pub fn session_passphrase ( self : Arc < Self > , passphrase : Option < String > ) -> Arc < Self > {
211
- let mut builder = unwrap_or_clone_arc ( self ) ;
212
- builder. session_passphrase = Zeroizing :: new ( passphrase) ;
213
- Arc :: new ( builder)
214
- }
215
-
216
- /// Set the pool max size for the SQLite stores given to
217
- /// [`ClientBuilder::session_paths`].
218
- ///
219
- /// Each store exposes an async pool of connections. This method controls
220
- /// the size of the pool. The larger the pool is, the more memory is
221
- /// consumed, but also the more the app is reactive because it doesn't need
222
- /// to wait on a pool to be available to run queries.
223
- ///
224
- /// See [`SqliteStoreConfig::pool_max_size`] to learn more.
225
- pub fn session_pool_max_size ( self : Arc < Self > , pool_max_size : Option < u32 > ) -> Arc < Self > {
226
- let mut builder = unwrap_or_clone_arc ( self ) ;
227
- builder. session_pool_max_size = pool_max_size
228
- . map ( |size| size. try_into ( ) . expect ( "`pool_max_size` is too large to fit in `usize`" ) ) ;
229
- Arc :: new ( builder)
230
- }
231
-
232
- /// Set the cache size for the SQLite stores given to
233
- /// [`ClientBuilder::session_paths`].
234
- ///
235
- /// Each store exposes a SQLite connection. This method controls the cache
236
- /// size, in **bytes (!)**.
237
- ///
238
- /// The cache represents data SQLite holds in memory at once per open
239
- /// database file. The default cache implementation does not allocate the
240
- /// full amount of cache memory all at once. Cache memory is allocated
241
- /// in smaller chunks on an as-needed basis.
242
- ///
243
- /// See [`SqliteStoreConfig::cache_size`] to learn more.
244
- pub fn session_cache_size ( self : Arc < Self > , cache_size : Option < u32 > ) -> Arc < Self > {
245
- let mut builder = unwrap_or_clone_arc ( self ) ;
246
- builder. session_cache_size = cache_size;
247
- Arc :: new ( builder)
248
- }
249
-
250
- /// Set the size limit for the SQLite WAL files of stores given to
251
- /// [`ClientBuilder::session_paths`].
252
- ///
253
- /// Each store uses the WAL journal mode. This method controls the size
254
- /// limit of the WAL files, in **bytes (!)**.
255
- ///
256
- /// See [`SqliteStoreConfig::journal_size_limit`] to learn more.
257
- pub fn session_journal_size_limit ( self : Arc < Self > , limit : Option < u32 > ) -> Arc < Self > {
258
- let mut builder = unwrap_or_clone_arc ( self ) ;
259
- builder. session_journal_size_limit = limit;
260
- Arc :: new ( builder)
261
- }
262
-
263
188
/// Tell the client that the system is memory constrained, like in a push
264
189
/// notification process for example.
265
190
///
@@ -425,50 +350,23 @@ impl ClientBuilder {
425
350
inner_builder. cross_process_store_locks_holder_name ( holder_name. clone ( ) ) ;
426
351
}
427
352
428
- let store_path = if let Some ( session_paths) = & builder. session_paths {
429
- // This is the path where both the state store and the crypto store will live.
430
- let data_path = Path :: new ( & session_paths. data_path ) ;
431
- // This is the path where the event cache store will live.
432
- let cache_path = Path :: new ( & session_paths. cache_path ) ;
433
-
434
- debug ! (
435
- data_path = %data_path. to_string_lossy( ) ,
436
- event_cache_path = %cache_path. to_string_lossy( ) ,
437
- "Creating directories for data (state and crypto) and cache stores." ,
438
- ) ;
439
-
440
- fs:: create_dir_all ( data_path) ?;
441
- fs:: create_dir_all ( cache_path) ?;
442
-
443
- let mut sqlite_store_config = if builder. system_is_memory_constrained {
444
- SqliteStoreConfig :: with_low_memory_config ( data_path)
445
- } else {
446
- SqliteStoreConfig :: new ( data_path)
447
- } ;
448
-
449
- sqlite_store_config =
450
- sqlite_store_config. passphrase ( builder. session_passphrase . as_deref ( ) ) ;
451
-
452
- if let Some ( size) = builder. session_pool_max_size {
453
- sqlite_store_config = sqlite_store_config. pool_max_size ( size) ;
454
- }
455
-
456
- if let Some ( size) = builder. session_cache_size {
457
- sqlite_store_config = sqlite_store_config. cache_size ( size) ;
458
- }
459
-
460
- if let Some ( limit) = builder. session_journal_size_limit {
461
- sqlite_store_config = sqlite_store_config. journal_size_limit ( limit) ;
353
+ let mut store_path = None ;
354
+ if let Some ( session_store) = builder. session_store {
355
+ match session_store. build ( ) ? {
356
+ #[ cfg( feature = "indexeddb" ) ]
357
+ SessionStoreResult :: IndexedDb { name, passphrase } => {
358
+ inner_builder = inner_builder. indexeddb_store ( & name, passphrase. as_deref ( ) ) ;
359
+ }
360
+ #[ cfg( feature = "sqlite" ) ]
361
+ SessionStoreResult :: Sqlite { config, cache_path, store_path : data_path } => {
362
+ inner_builder = inner_builder
363
+ . sqlite_store_with_config_and_cache_path ( config, Some ( cache_path) ) ;
364
+ store_path = Some ( data_path) ;
365
+ }
462
366
}
463
-
464
- inner_builder = inner_builder
465
- . sqlite_store_with_config_and_cache_path ( sqlite_store_config, Some ( cache_path) ) ;
466
-
467
- Some ( data_path. to_owned ( ) )
468
367
} else {
469
- debug ! ( "Not using a store path." ) ;
470
- None
471
- } ;
368
+ debug ! ( "Not using a session store." )
369
+ }
472
370
473
371
// Determine server either from URL, server name or user ID.
474
372
inner_builder = match builder. homeserver_cfg {
@@ -646,14 +544,32 @@ impl ClientBuilder {
646
544
}
647
545
}
648
546
649
- /// The store paths the client will use when built.
650
- #[ derive( Clone ) ]
651
- struct SessionPaths {
652
- /// The path that the client will use to store its data.
653
- data_path : String ,
654
- /// The path that the client will use to store its caches. This path can be
655
- /// the same as the data path if you prefer to keep everything in one place.
656
- cache_path : String ,
547
+ #[ cfg( feature = "sqlite" ) ]
548
+ #[ matrix_sdk_ffi_macros:: export]
549
+ impl ClientBuilder {
550
+ /// Tell the client to use sqlite to store session data.
551
+ pub fn session_store_sqlite (
552
+ self : Arc < Self > ,
553
+ config : Arc < crate :: session_store:: SqliteSessionStoreBuilder > ,
554
+ ) -> Arc < Self > {
555
+ let mut builder = unwrap_or_clone_arc ( self ) ;
556
+ builder. session_store = Some ( SessionStoreConfig :: Sqlite ( config. as_ref ( ) . clone ( ) ) ) ;
557
+ Arc :: new ( builder)
558
+ }
559
+ }
560
+
561
+ #[ cfg( feature = "indexeddb" ) ]
562
+ #[ matrix_sdk_ffi_macros:: export]
563
+ impl ClientBuilder {
564
+ /// Tell the client to use IndexedDb to store session data.
565
+ pub fn session_store_indexeddb (
566
+ self : Arc < Self > ,
567
+ config : Arc < crate :: session_store:: IndexedDbSessionStoreBuilder > ,
568
+ ) -> Arc < Self > {
569
+ let mut builder = unwrap_or_clone_arc ( self ) ;
570
+ builder. session_store = Some ( SessionStoreConfig :: IndexedDb ( config. as_ref ( ) . clone ( ) ) ) ;
571
+ Arc :: new ( builder)
572
+ }
657
573
}
658
574
659
575
#[ derive( Clone , uniffi:: Record ) ]
0 commit comments