download method

  1. @override
Stream<List<int>> download(
  1. RpcFileReference file, {
  2. Duration timeout = const Duration(minutes: 15),
  3. RpcCancellationToken? cancellationToken,
  4. int maxAttempts = 3,
})
override

Implementation

@override
Stream<List<int>> download(
  RpcFileReference file, {
  Duration timeout = const Duration(minutes: 15),
  RpcCancellationToken? cancellationToken,
  int maxAttempts = 3,
}) async* {
  if (maxAttempts < 1) {
    throw ArgumentError.value(
      maxAttempts,
      'maxAttempts',
      'Use at least one attempt.',
    );
  }
  if (_state == _SidecarState.closing ||
      _state == _SidecarState.closed ||
      _state == _SidecarState.failed) {
    throw _terminalError ?? const BackendClosedException();
  }
  if (cancellationToken?.isCancelled ?? false) {
    throw const RpcCancelledException('file.download');
  }
  final localPath = file.localPath;
  if (localPath == null) {
    throw const BackendProtocolException(
      'The Sidecar file reference is missing its managed local path.',
    );
  }
  if (file.isExpired) {
    await _deleteDownloadedFile(localPath);
    throw const RpcFileExpiredException();
  }

  Object? requestedError;
  final timeoutTimer = Timer(timeout, () {
    requestedError = TimeoutException(
      'Sidecar file download timed out.',
      timeout,
    );
  });
  final cancellationSubscription = cancellationToken?.onCancel.listen((_) {
    requestedError = const RpcCancelledException('file.download');
  });
  try {
    final source = _readSidecarFileWithRetries(
      localPath,
      file.size,
      maxAttempts,
      () => requestedError,
    );
    await for (final chunk in verifyRpcFileDownload(source, file)) {
      final error = requestedError;
      if (error != null) throw error;
      yield chunk;
    }
    final error = requestedError;
    if (error != null) throw error;
  } on TimeoutException {
    rethrow;
  } on RpcCancelledException {
    rethrow;
  } on BackendConnectionException {
    rethrow;
  } on FileSystemException catch (error) {
    throw BackendTransportException(
      'Could not read the Sidecar file ${file.name}.',
      cause: error,
    );
  } finally {
    timeoutTimer.cancel();
    if (cancellationSubscription != null) {
      unawaited(cancellationSubscription.cancel());
    }
    await _deleteDownloadedFile(localPath);
  }
}