In particular, what happens if the top-level request triggers some quasi-blocking messages to other canisters?
Not sure what you mean by “quai-blocking”, but all messages are asynchronous, i.e., sender of a message will not wait for the message reply to come back. So in other words, a canister is never blocked, when it finishes processing current message, it’ll just pick up next one from its incoming message queue. Of course queue size is limited, in which case the sender will get a error back (in the form of a reply message). The space of replies (success or error) are pre-reserved, so the sender will know at sending point whether it will receive a reply.
There is also a max cycle limit per message, so if a message takes too long to run, the execution will abort. So nothing should block a canister for long.
all the batch input is collected before processing begins
… seem to imply that the outgoing messages can’t be processed until the next round
Not sure what you mean by “outgoing”, but inter-canister calls to the same subnet can interleave with messages from the input batch. Inter-canister calls to a different subnet will be picked up for delivery periodically.
Although input batches are picked up in order, there may still be residual messages in the system when the next batch is picked up for execution. It all depends on capacity. There is no strict guarantee on the order of messages that a canister processes.
So inter-canister messages for the same subnet are not considered part of the input batch (which includes those from user and from other subnets). There may be a worry that at some point there can be too many pending messages in the system, but if each canister has a max input queue size, the total capacity is bounded, at which point, messages are dropped and sender will receive an error in reply.