Fixes #51
Test script below. It assumes you execute it in different mount than your /tmp/. Feel free to modify and use it to copy some actual files instead of str_repeat and change it so it does not fill up both disks. Ideally run from tmpfs.
<?php
use Amp\ByteStream\CannotWriteChunkException;
use Amp\ByteStream\ResourceOutputStream;
use Amp\Loop;
require __DIR__ . '/../vendor/autoload.php';
Loop::run(function () {
$chunkSize = null;
$out = new ResourceOutputStream(\fopen('foo', 'wb'), $chunkSize);
$fallback = new ResourceOutputStream(\fopen('/tmp/bar', 'wb'), $chunkSize);
$str = str_repeat('a', 8192);
$written = 0;
try {
while (($size = yield $out->write($str)) !== null) {
$written += $size;
}
} catch (CannotWriteChunkException $exception) {
$written += $exception->getFailingPositionInChunk();
$written += yield $fallback->write(substr($str, $exception->getFailingPositionInChunk()));
$out = $fallback;
}
echo 'written '.$written.PHP_EOL.'file sizes: '.(filesize('foo') + filesize('/tmp/bar'));
});
I don't see a good way how to write useful phpunit test for this, gave a lot of tries. Closest I could come up with is
public function testCannotWriteChunkException()
{
$server = \stream_socket_server('localhost:8111', $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);
$watcherId = Loop::onReadable($server, static function () use ($server, &$watcherId) {
fread(\stream_socket_accept($server, 0), 1);
Loop::cancel($watcherId);
});
$stream = new ResourceOutputStream(stream_socket_client('localhost:8111'));
self::expectException(CannotWriteChunkException::class);
wait($stream->write(str_repeat('-', 8 ** 7)));
}
But even that works only on MacOS and Windows, not Linux