@@ -19,11 +19,14 @@ use mas_matrix::{HomeserverConnection, ReadOnlyHomeserverConnection};
1919use mas_matrix_synapse:: SynapseConnection ;
2020use mas_policy:: PolicyFactory ;
2121use mas_router:: UrlBuilder ;
22+ use mas_storage:: RepositoryAccess ;
23+ use mas_storage_pg:: PgRepository ;
2224use mas_templates:: { SiteConfigExt , TemplateLoadingError , Templates } ;
2325use sqlx:: {
2426 ConnectOptions , PgConnection , PgPool ,
2527 postgres:: { PgConnectOptions , PgPoolOptions } ,
2628} ;
29+ use tokio_util:: { sync:: CancellationToken , task:: TaskTracker } ;
2730use tracing:: { Instrument , log:: LevelFilter } ;
2831
2932pub async fn password_manager_from_config (
@@ -377,6 +380,66 @@ pub async fn database_connection_from_config_with_options(
377380 . context ( "could not connect to the database" )
378381}
379382
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+
380443/// Create a clonable, type-erased [`HomeserverConnection`] from the
381444/// configuration
382445pub fn homeserver_connection_from_config (
0 commit comments