/// For all `canisters` concurrently attempts to first refund the remaining
/// cycles to the used wallet canisters, then attempts to stop the canisters
/// where refunding was successful, and finally attempts to delete the
/// successfully stopped canisters. If there are no wallets provided it
/// will directly stop and delete the given canisters.
For all `canisters` concurrently attempts to first refund the remaining
cycles to the used wallet canisters, then attempts to stop the canisters
where refunding was successful, and finally attempts to delete the
successfully stopped canisters. If there are no wallets provided it
will directly stop and delete the given canisters.
For all ` canisters ` concurrently attempts to first refund the remaining cycles to the used wallet canisters then attempts to stop the canisters where refunding was successful and finally attempts to delete the successfully stopped canisters . If there are no wallets provided it will directly stop and delete the given canisters .
pub async fn cleanup(canisters: Vec<CanisterLocator<'_>>) {
    pub async fn return_cycles<'a, 'b>(
        src: Canister<'a>,
        dst: Canister<'b>,
    ) -> Result<Canister<'a>, String> {
        #[derive(CandidType, Deserialize, Debug)]
        struct DepositCycleArgs {
            canister_id: Principal,
        }
        let res: Result<String, String> = src
            .update_(
                "return_cycles",
                candid,
                (DepositCycleArgs {
                    canister_id: Principal::from_str(&dst.canister_id().to_string()).unwrap(),
                },),
            )
            .await;
        res.map(|_| src)
    }
    fn print_error<'a>(
        action: &str,
        i: usize,
        result: Result<Canister<'a>, String>,
    ) -> Result<Canister<'a>, String> {
        if let Err(e) = result.as_ref() {
            println!("{} {} failed: {}", action, i, e);
        }
        result
    }
    pub async fn stop_canister(canister: Canister<'_>) -> Result<Canister<'_>, String> {
        canister.stop().await.map(|_| canister)
    }
    pub async fn delete_canister(canister: Canister<'_>) -> Result<Canister<'_>, String> {
        canister.delete().await.map(|_| canister)
    }
    let canisters_to_wallets = canisters
        .iter()
        .map(|locator| (locator.canister(), locator.wallet()))
        .filter(|(_, wallet)| wallet.is_some())
        .map(|(canister, wallet)| (canister, wallet.unwrap()))
        .collect::<Vec<(Canister, Canister)>>();
    let canisters: Vec<Canister> = if !canisters_to_wallets.is_empty() {
        println!("Sleeping 120s to give canisters a chance to catch up with the backlog");
        std::thread::sleep(Duration::from_secs(120));
        println!("Refunding remaining cycles");
        let refunded: Vec<Result<Canister, String>> = parallel_async(
            canisters_to_wallets,
            |(canister, wallet)| return_cycles(canister, wallet),
            |i, res| print_error("Refunding cycles for canister", i, res),
        )
        .await;
        refunded
            .into_iter()
            .filter(|x| x.is_ok())
            .map(|x| x.unwrap())
            .collect()
    } else {
        canisters.iter().map(|locator| locator.canister()).collect()
    };
    println!("Stopping canisters");
    let canisters: Vec<Result<Canister, String>> =
        parallel_async(canisters, stop_canister, |i, res| {
            print_error("Stopping canister", i, res)
        })
        .await;
    println!("Deleting canisters");
    let _: Vec<Result<Canister, String>> = parallel_async(
        canisters
            .into_iter()
            .filter(|x| x.is_ok())
            .map(|x| x.unwrap())
            .collect::<Vec<Canister>>(),
        delete_canister,
        |i, res| print_error("Deleting canister", i, res),
    )
    .await;
}
pub async fn cleanup ( canisters : Vec < CanisterLocator < ' _ > > ) { pub async fn return_cycles < ' a , ' b > ( src : Canister < ' a > , dst : Canister < ' b > , ) -> Result < Canister < ' a > , String > { # [ derive ( CandidType Deserialize Debug ) ] struct DepositCycleArgs { canister_id : Principal , } let res : Result < String , String > = src . update_ ( " " , candid , ( DepositCycleArgs { canister_id : Principal :: from_str ( & dst . canister_id ( ) . to_string ( ) ) . unwrap ( ) , } , ) , ) . await ; res . map ( | _ | src ) } fn print_error < ' a > ( action : & str , i : usize , result : Result < Canister < ' a > , String > , ) -> Result < Canister < ' a > , String > { if let Err ( e ) = result . as_ref ( ) { println ! ( " " action i e ) ; } result } pub async fn stop_canister ( canister : Canister < ' _ > ) -> Result < Canister < ' _ > , String > { canister . stop ( ) . await . map ( | _ | canister ) } pub async fn delete_canister ( canister : Canister < ' _ > ) -> Result < Canister < ' _ > , String > { canister . delete ( ) . await . map ( | _ | canister ) } let canisters_to_wallets = canisters . iter ( ) . map ( | locator | ( locator . canister ( ) , locator . wallet ( ) ) ) . filter ( | ( _ , wallet ) | wallet . is_some ( ) ) . map ( | ( canister , wallet ) | ( canister , wallet . unwrap ( ) ) ) . collect :: < Vec < ( Canister , Canister ) > > ( ) ; let canisters : Vec < Canister > = if ! canisters_to_wallets . is_empty ( ) { println ! ( " " ) ; std :: thread :: sleep ( Duration :: from_secs ( 120 ) ) ; println ! ( " " ) ; let refunded : Vec < Result < Canister , String > > = parallel_async ( canisters_to_wallets , | ( canister , wallet ) | return_cycles ( canister , wallet ) , | i , res | print_error ( " " , i , res ) , ) . await ; refunded . into_iter ( ) . filter ( | x | x . is_ok ( ) ) . map ( | x | x . unwrap ( ) ) . collect ( ) } else { canisters . iter ( ) . map ( | locator | locator . canister ( ) ) . collect ( ) } ; println ! ( " " ) ; let canisters : Vec < Result < Canister , String > > = parallel_async ( canisters , stop_canister , | i , res | { print_error ( " " , i , res ) } ) . await ; println ! ( " " ) ; let _ : Vec < Result < Canister , String > > = parallel_async ( canisters . into_iter ( ) . filter ( | x | x . is_ok ( ) ) . map ( | x | x . unwrap ( ) ) . collect :: < Vec < Canister > > ( ) , delete_canister , | i , res | print_error ( " " , i , res ) , ) . await ; }
For all `canisters` concurrently attempts to first refund the remaining
cycles to the used wallet canisters, then attempts to stop the canisters
where refunding was successful, and finally attempts to delete the
successfully stopped canisters.
For all ` canisters ` concurrently attempts to first refund the remaining cycles to the used wallet canisters then attempts to stop the canisters where refunding was successful and finally attempts to delete the successfully stopped canisters .
canisters
Vec<CanisterLocator<'_>>