@@ -19,11 +19,14 @@ use mas_matrix::{HomeserverConnection, ReadOnlyHomeserverConnection};
19
19
use mas_matrix_synapse:: SynapseConnection ;
20
20
use mas_policy:: PolicyFactory ;
21
21
use mas_router:: UrlBuilder ;
22
+ use mas_storage:: RepositoryAccess ;
23
+ use mas_storage_pg:: PgRepository ;
22
24
use mas_templates:: { SiteConfigExt , TemplateLoadingError , Templates } ;
23
25
use sqlx:: {
24
26
ConnectOptions , PgConnection , PgPool ,
25
27
postgres:: { PgConnectOptions , PgPoolOptions } ,
26
28
} ;
29
+ use tokio_util:: { sync:: CancellationToken , task:: TaskTracker } ;
27
30
use tracing:: { Instrument , log:: LevelFilter } ;
28
31
29
32
pub async fn password_manager_from_config (
@@ -377,6 +380,66 @@ pub async fn database_connection_from_config_with_options(
377
380
. context ( "could not connect to the database" )
378
381
}
379
382
383
+ /// Update the policy factory dynamic data from the database and spawn a task to
384
+ /// periodically update it
385
+ // XXX: this could be put somewhere else?
386
+ pub async fn load_policy_factory_dynamic_data_continuously (
387
+ policy_factory : & Arc < PolicyFactory > ,
388
+ pool : & PgPool ,
389
+ cancellation_token : CancellationToken ,
390
+ task_tracker : & TaskTracker ,
391
+ ) -> Result < ( ) , anyhow:: Error > {
392
+ let policy_factory = policy_factory. clone ( ) ;
393
+ let pool = pool. clone ( ) ;
394
+
395
+ load_policy_factory_dynamic_data ( & policy_factory, & pool) . await ?;
396
+
397
+ task_tracker. spawn ( async move {
398
+ let mut interval = tokio:: time:: interval ( Duration :: from_secs ( 60 ) ) ;
399
+
400
+ loop {
401
+ tokio:: select! {
402
+ ( ) = cancellation_token. cancelled( ) => {
403
+ return ;
404
+ }
405
+ _ = interval. tick( ) => { }
406
+ }
407
+
408
+ if let Err ( err) = load_policy_factory_dynamic_data ( & policy_factory, & pool) . await {
409
+ tracing:: error!(
410
+ error = ?err,
411
+ "Failed to load policy factory dynamic data"
412
+ ) ;
413
+ cancellation_token. cancel ( ) ;
414
+ return ;
415
+ }
416
+ }
417
+ } ) ;
418
+
419
+ Ok ( ( ) )
420
+ }
421
+
422
+ /// Update the policy factory dynamic data from the database
423
+ #[ tracing:: instrument( name = "policy.load_dynamic_data" , skip_all, err( Debug ) ) ]
424
+ pub async fn load_policy_factory_dynamic_data (
425
+ policy_factory : & PolicyFactory ,
426
+ pool : & PgPool ,
427
+ ) -> Result < ( ) , anyhow:: Error > {
428
+ let mut repo = PgRepository :: from_pool ( pool)
429
+ . await
430
+ . context ( "Failed to acquire database connection" ) ?;
431
+
432
+ if let Some ( data) = repo. policy_data ( ) . get ( ) . await ? {
433
+ let id = data. id ;
434
+ let updated = policy_factory. set_dynamic_data ( data) . await ?;
435
+ if updated {
436
+ tracing:: info!( policy_data. id = %id, "Loaded dynamic policy data from the database" ) ;
437
+ }
438
+ }
439
+
440
+ Ok ( ( ) )
441
+ }
442
+
380
443
/// Create a clonable, type-erased [`HomeserverConnection`] from the
381
444
/// configuration
382
445
pub fn homeserver_connection_from_config (
0 commit comments