downloadUpdate method

Future<String> downloadUpdate(
  1. SankofaUpdate update, {
  2. void onProgress(
    1. int received,
    2. int total
    )?,
  3. Duration timeout = const Duration(minutes: 5),
})

Download the envelope discovered by checkForUpdate and stage it on disk for tryApplyStagedKbcPatch to pick up on the next launch. Streams the response so onProgress fires on every chunk with the running (received, total) bytes — drives a progress bar without buffering the whole envelope in memory.

The streamed bytes are verified against SankofaUpdate.sha256 before the file is moved into place; a corrupt download deletes the partial file and throws KbcFetchException.

Returns the absolute on-disk path of the staged envelope. Hosts rarely need this — kept for debugging and tests.

Telemetry: emits kbc_patch_downloaded on success and kbc_apply_failed{phase=download} on transport / SHA failures.

Implementation

Future<String> downloadUpdate(
  SankofaUpdate update, {
  void Function(int received, int total)? onProgress,
  Duration timeout = const Duration(minutes: 5),
}) async {
  _assertReady();
  try {
    final path = await kbc_fetch.downloadKbcUpdateToFile(
      update,
      onProgress: onProgress,
      timeout: timeout,
    );
    _reportKbcEvent(
      eventType: 'kbc_patch_downloaded',
      bundleLabel: update.label,
      releaseId: update.releaseId,
      extra: {'size_bytes': update.sizeBytes, 'staged_path': path},
    );
    return path;
  } catch (err, st) {
    final stack = _formatKbcStackTrace(st);
    _reportKbcEvent(
      eventType: 'kbc_apply_failed',
      bundleLabel: update.label,
      releaseId: update.releaseId,
      errorMessage: err.toString(),
      extra: {
        'phase': 'download',
        'cause_class': err.runtimeType.toString(),
        if (stack != null) 'stack_trace': stack,
      },
    );
    rethrow;
  }
}