Batch instance teardown so its instance reads do not scale with the token count
cancelInstance()/failInstance() flip the instance terminal, then cancelLiveTokens() cancels each live token. This stops that bulk path reading the instance table once per token:
- The token cascade is extracted from cancel(); cancel() keeps the completion and stall recheck (its superseded-branch / discriminator / timer callers run on a still-running instance and need it), but the bulk teardown skips it, since the instance is already terminal and the rechecks could only early-return.
- The subprocess-child teardown is batched: cancelLiveTokens() loads the running children of all cancelled tokens in one parent-token IN query rather than one lookup per token.
- cancelTimers() uses one loadMultiple() instead of a query per id.
A kernel test tears a two-branch and a five-branch instance down and asserts the instance-table read count is identical (O(1) in the branch count). Pre-1.0, no schema change.