in src/Downloader.php [253:330]
private function writeSequential(array &$context): GuzzleHttp\Promise\Promise
{
return GuzzleHttp\Promise\Coroutine::of(function () use (&$context) {
// get object meta
$request = new Models\HeadObjectRequest();
Utils::copyRequest($request, $context['request']);
yield $this->client->headObjectAsync($request)->then(
function (Models\HeadObjectResult $result) use (&$context) {
$pos = $context['epos'];
$context['epos'] = $pos < 0 ? $result->contentLength : min($pos, $result->contentLength);
},
);
// download parallel & write sequential
$context['errors'] = [];
$context['parts'] = [];
$context['wstart'] = $context['pos'];
$downloadFns = function () use (&$context) {
foreach (self::iterPart($context) as $args) {
/**
* @var Models\GetObjectRequest $request
*/
$request = clone $context['request'];
$request->rangeHeader = sprintf('bytes=%d-%d', $args[0], $args[0] + $args[1] - 1);
$request->rangeBehavior = 'standard';
$request->progressFn = null;
yield $this->client->getObjectAsync($request)->otherwise(
function ($reason) use (&$context) {
$context['errors'][] = $reason;
return GuzzleHttp\Promise\Create::rejectionFor($reason);
},
);
if (!empty($context['errors'])) {
break;
}
}
};
$each = new GuzzleHttp\Promise\EachPromise(
$downloadFns(),
[
'concurrency' => $context['parallel_num'],
'fulfilled' => function (Models\GetObjectResult $result, $key) use (&$context) {
$rangeStart = $result->contentRange != null ? Utils::parseContentRange($result->contentRange) : 0;
$rangeStart = \is_array($rangeStart) ? $rangeStart[0] : 0;
$context['parts'][] = ['start' => $rangeStart, 'result' => $result];
self::drainPart($context);
return $result;
}
]
);
yield $each->promise();
// remains parts
self::drainPart($context);
if (!empty($context['errors'])) {
throw end($context['errors']);
}
if (!empty($context['parts'])) {
throw new \RuntimeException('There are still unsaved parts.');
}
})->then(
function ($result) use (&$context) {
$res = new Models\DownloadResult();
$res->written = $context['epos'] - $context['pos'];
return $res;
},
function ($reason) use (&$context) {
return GuzzleHttp\Promise\Create::rejectionFor(new Exception\DownloadException(
$context['filepath'] ?? '',
$reason
));
}
);
}