Deploying a wasm in the middle of a multi-step process

I have a few questions about how upgrading a canister can affect outstanding calls that kick off multi-step process. The reason I’m asking is if there are any scenarios where upgrading the canister could halt a multi-step process that involves sequential, asynchronous calls to a different canister, and if I need to implement logic that stops one of these multi-step processes from being kicked off before performing and upgrade.

Here are the scenarios I’m wondering about:

  1. In the middle of a synchronous multi-step process (multiple inter-canister calls made, request waits until all complete and then returns).
actor {
  //...
  public func startProcess() : async () {
    // step 1, call ICP ledger balance
    await LEDGER.account_balance({ account });

    // what if the wasm upgrade happens here?

    // Do this a few more times to simulate other things happening
    // step 2,
    await LEDGER.account_balance({ account });

    // step 3,
    await LEDGER.account_balance({ account });

    // or what if the wasm upgrade happens here?

    // step 4,
    await LEDGER.account_balance({ account });
  };
}
  1. In the middle of an asynchronous multi-step process (multiple inter-canister calls made, request returns immediately, but async process runs in background).
actor {
  public func doThisAndReturnAsync() : async Nat {
    let requestId = getNextRequestId();
    ignore BTree.insert(requests, Nat.compare, requestId, #s1);
    // don't wait for the async process to complete
    ignore startAsyncProcess(requestId);

    requestId;
  };

  func startAsyncProcess(requestId : Nat) : async () {
    // request state held in some map
    // step 1, call ICP ledger balance
    updateRequestState(requestId, await LEDGER.account_balance({ account }));

    // what if the upgrade happens here?

    // Do this a few more times to simulate other things happening
    // step 2,
    updateRequestState(requestId, await LEDGER.account_balance({ account }));

    // step 3,
    updateRequestState(requestId, await LEDGER.account_balance({ account }));

    // or what if the upgrade happens here?

    // step 4,
    updateRequestState(requestId, await LEDGER.account_balance({ account }));
  };
}

It depends a lot on how the upgrade happens. If your target canister is upgraded with a ‘naked’ dfx canister install --mode upgrade then you shouldn’t run into any issues since the upgrade will happen invisibly to you.
The ICP ledger, just like any other canister upgrade run by the NNS, first stops the canister, then installs the new code, and restarts the canister. This means that any of your requests to the ledger may fail with Canister is stopped

In your case I would say you have two options: Either stop the process during upgrades, or add retry logic to your process so that it can handle temporarily unavailable canisters.