docs: function createTimeoutPromise(task, timeoutMs, timeoutCancellable, processCancellable, context) {
    return Promises.delay(timeoutMs, timeoutCancellable).then(
      triggered => {
        if (triggered) {
          context.info(`Timed out while waiting for ${task.name}`);
          // Cancel/short-circuit the process tasks
          if (processCancellable && typeof processCancellable.cancel === 'function') {
            const completed = processCancellable.cancel();
            if (completed) {
              context.warn(`Timeout was triggered, but task ${task.name} process is also already completed!`);
              return false;
            }
          }
          const timeoutOpts = {overrideCompleted: false, overrideUnstarted: false, reverseAttempt: true};
          task.timeout(new TimeoutError(`Ran out of time to complete ${task.name}`), timeoutOpts, true);
        }
        return triggered;
      },
      err => {
        if (isInstanceOf(err, DelayCancelledError)) {
          // The timeout promise was cancelled, which means that the main completing promise must have completed and cancelled the timeout
          context.debug(`Timeout cancelled after ${task.name} completed - ${err.message}`);
          return false; // a DelayCancelledError will only be thrown if the timeout has NOT triggered
        } else {
          // The timeout promise rejected with an unexpected error!
          context.error(`Timeout failed with an unexpected error while waiting for ${task.name}`, err);
          throw err;
        }
      }
    );
  }