1- use std:: { collections:: HashMap , process:: ExitCode } ;
1+ use std:: { collections:: HashMap , process:: ExitCode , sync :: atomic :: Ordering , time :: Duration } ;
22
33use anyhow:: Context ;
44use camino:: Utf8PathBuf ;
@@ -12,8 +12,10 @@ use mas_storage::SystemClock;
1212use mas_storage_pg:: MIGRATOR ;
1313use rand:: thread_rng;
1414use sqlx:: { Connection , Either , PgConnection , postgres:: PgConnectOptions , types:: Uuid } ;
15- use syn2mas:: { LockedMasDatabase , MasWriter , SynapseReader , synapse_config} ;
16- use tracing:: { Instrument , error, info_span, warn} ;
15+ use syn2mas:: {
16+ LockedMasDatabase , MasWriter , Progress , ProgressStage , SynapseReader , synapse_config,
17+ } ;
18+ use tracing:: { Instrument , error, info, info_span, warn} ;
1719
1820use crate :: util:: { DatabaseConnectOptions , database_connection_from_config_with_options} ;
1921
@@ -248,7 +250,11 @@ impl Options {
248250 #[ allow( clippy:: disallowed_methods) ]
249251 let mut rng = thread_rng ( ) ;
250252
251- // TODO progress reporting
253+ let progress = Progress :: default ( ) ;
254+
255+ let occasional_progress_logger_task =
256+ tokio:: spawn ( occasional_progress_logger ( progress. clone ( ) ) ) ;
257+
252258 let mas_matrix = MatrixConfig :: extract ( figment) ?;
253259 eprintln ! ( "\n \n " ) ;
254260 syn2mas:: migrate (
@@ -258,11 +264,45 @@ impl Options {
258264 & clock,
259265 & mut rng,
260266 provider_id_mappings,
267+ & progress,
261268 )
262269 . await ?;
263270
271+ occasional_progress_logger_task. abort ( ) ;
272+
264273 Ok ( ExitCode :: SUCCESS )
265274 }
266275 }
267276 }
268277}
278+
279+ /// Logs progress every 30 seconds, as a lightweight alternative to a progress
280+ /// bar. For most deployments, the migration will not take 30 seconds so this
281+ /// will not be relevant. In other cases, this will give the operator an idea of
282+ /// what's going on.
283+ async fn occasional_progress_logger ( progress : Progress ) {
284+ loop {
285+ tokio:: time:: sleep ( Duration :: from_secs ( 30 ) ) . await ;
286+ match & * * progress. get_current_stage ( ) {
287+ ProgressStage :: SettingUp => {
288+ info ! ( name: "progress" , "still setting up" ) ;
289+ }
290+ ProgressStage :: MigratingData {
291+ entity,
292+ migrated,
293+ approx_count,
294+ } => {
295+ let migrated = migrated. load ( Ordering :: Relaxed ) ;
296+ #[ allow( clippy:: cast_precision_loss) ]
297+ let percent = ( f64:: from ( migrated) / * approx_count as f64 ) * 100.0 ;
298+ info ! ( name: "progress" , "migrating {entity}: {migrated}/~{approx_count} (~{percent:.1}%)" ) ;
299+ }
300+ ProgressStage :: RebuildIndex { index_name } => {
301+ info ! ( name: "progress" , "still waiting for rebuild of index {index_name}" ) ;
302+ }
303+ ProgressStage :: RebuildConstraint { constraint_name } => {
304+ info ! ( name: "progress" , "still waiting for rebuild of constraint {constraint_name}" ) ;
305+ }
306+ }
307+ }
308+ }
0 commit comments