@@ -32,6 +32,44 @@ fn most_recent_activate_time(
3232 }
3333}
3434
35+ /// Given the name of a background task, wait for it to complete if it's
36+ /// running, then return the last polled `BackgroundTask` object. Panics if the
37+ /// task has never been activated.
38+ pub async fn wait_background_task (
39+ internal_client : & ClientTestContext ,
40+ task_name : & str ,
41+ ) -> BackgroundTask {
42+ // Wait for the task to finish
43+ let last_task_poll = wait_for_condition (
44+ || async {
45+ let task = NexusRequest :: object_get (
46+ internal_client,
47+ & format ! ( "/bgtasks/view/{task_name}" ) ,
48+ )
49+ . execute_and_parse_unwrap :: < BackgroundTask > ( )
50+ . await ;
51+
52+ // Wait until the task has actually run and then is idle
53+ if matches ! ( & task. current, CurrentStatus :: Idle ) {
54+ match & task. last {
55+ LastResult :: Completed ( _) => Ok ( task) ,
56+ LastResult :: NeverCompleted => {
57+ panic ! ( "task never activated" )
58+ }
59+ }
60+ } else {
61+ Err ( CondCheckError :: < ( ) > :: NotYet )
62+ }
63+ } ,
64+ & Duration :: from_millis ( 500 ) ,
65+ & Duration :: from_secs ( 60 ) ,
66+ )
67+ . await
68+ . unwrap ( ) ;
69+
70+ last_task_poll
71+ }
72+
3573/// Given the name of a background task, activate it, then wait for it to
3674/// complete. Return the last polled `BackgroundTask` object.
3775pub async fn activate_background_task (
@@ -337,3 +375,68 @@ pub async fn run_replacement_tasks_to_completion(
337375 . await
338376 . unwrap ( ) ;
339377}
378+
379+ pub async fn wait_tuf_artifact_replication_step (
380+ internal_client : & ClientTestContext ,
381+ ) -> TufArtifactReplicationStatus {
382+ let last_background_task =
383+ wait_background_task ( & internal_client, "tuf_artifact_replication" )
384+ . await ;
385+
386+ let LastResult :: Completed ( last_result_completed) =
387+ last_background_task. last
388+ else {
389+ panic ! (
390+ "unexpected {:?} returned from tuf_artifact_replication task" ,
391+ last_background_task. last,
392+ ) ;
393+ } ;
394+
395+ let status = serde_json:: from_value :: < TufArtifactReplicationStatus > (
396+ last_result_completed. details ,
397+ )
398+ . unwrap ( ) ;
399+ assert_eq ! ( status. requests_err, 0 ) ;
400+ status
401+ }
402+
403+ pub async fn run_tuf_artifact_replication_step (
404+ internal_client : & ClientTestContext ,
405+ ) -> TufArtifactReplicationStatus {
406+ let last_background_task =
407+ activate_background_task ( & internal_client, "tuf_artifact_replication" )
408+ . await ;
409+
410+ let LastResult :: Completed ( last_result_completed) =
411+ last_background_task. last
412+ else {
413+ panic ! (
414+ "unexpected {:?} returned from tuf_artifact_replication task" ,
415+ last_background_task. last,
416+ ) ;
417+ } ;
418+
419+ let status = serde_json:: from_value :: < TufArtifactReplicationStatus > (
420+ last_result_completed. details ,
421+ )
422+ . unwrap ( ) ;
423+ assert_eq ! ( status. requests_err, 0 ) ;
424+ status
425+ }
426+
427+ /// Run the `tuf_artifact_replication` task until the status indicates the task
428+ /// has stabilized: no outstanding requests, and no local repositories. Panics
429+ /// if the status does not change between runs.
430+ pub async fn run_tuf_artifact_replication_to_completion (
431+ internal_client : & ClientTestContext ,
432+ ) {
433+ let mut status = run_tuf_artifact_replication_step ( internal_client) . await ;
434+ while status. requests_outstanding > 0 || status. local_repos > 0 {
435+ let new_status =
436+ run_tuf_artifact_replication_step ( internal_client) . await ;
437+ if new_status == status {
438+ panic ! ( "TUF artifact replication stalled: {new_status:?}" ) ;
439+ }
440+ status = new_status;
441+ }
442+ }
0 commit comments