Skip to content

Commit 67bfd18

Browse files
committed
AsyncS3: throw FilesystemOperationFailed exceptions in case upload or listContent fails
1 parent 22af5a3 commit 67bfd18

File tree

2 files changed

+82
-33
lines changed

2 files changed

+82
-33
lines changed

src/AsyncAwsS3/AsyncAwsS3Adapter.php

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,18 @@
2727
use League\Flysystem\UnableToCheckDirectoryExistence;
2828
use League\Flysystem\UnableToCheckFileExistence;
2929
use League\Flysystem\UnableToCopyFile;
30+
use League\Flysystem\UnableToCreateDirectory;
31+
use League\Flysystem\UnableToDeleteDirectory;
3032
use League\Flysystem\UnableToDeleteFile;
3133
use League\Flysystem\UnableToGeneratePublicUrl;
3234
use League\Flysystem\UnableToGenerateTemporaryUrl;
35+
use League\Flysystem\UnableToListContents;
3336
use League\Flysystem\UnableToMoveFile;
3437
use League\Flysystem\UnableToProvideChecksum;
3538
use League\Flysystem\UnableToReadFile;
3639
use League\Flysystem\UnableToRetrieveMetadata;
3740
use League\Flysystem\UnableToSetVisibility;
41+
use League\Flysystem\UnableToWriteFile;
3842
use League\Flysystem\UrlGeneration\PublicUrlGenerator;
3943
use League\Flysystem\UrlGeneration\TemporaryUrlGenerator;
4044
use League\Flysystem\Visibility;
@@ -177,32 +181,42 @@ public function deleteDirectory(string $path): void
177181

178182
$objects = [];
179183
$params = ['Bucket' => $this->bucket, 'Prefix' => $prefix];
180-
$result = $this->client->listObjectsV2($params);
181-
/** @var AwsObject $item */
182-
foreach ($result->getContents() as $item) {
183-
$key = $item->getKey();
184-
if (null !== $key) {
185-
$objects[] = new ObjectIdentifier(['Key' => $key]);
184+
185+
try {
186+
$result = $this->client->listObjectsV2($params);
187+
/** @var AwsObject $item */
188+
foreach ($result->getContents() as $item) {
189+
$key = $item->getKey();
190+
if (null !== $key) {
191+
$objects[] = new ObjectIdentifier(['Key' => $key]);
192+
}
186193
}
187-
}
188194

189-
if (empty($objects)) {
190-
return;
191-
}
195+
if (empty($objects)) {
196+
return;
197+
}
192198

193-
foreach (array_chunk($objects, 1000) as $chunk) {
194-
$this->client->deleteObjects([
195-
'Bucket' => $this->bucket,
196-
'Delete' => ['Objects' => $chunk],
197-
]);
199+
foreach (array_chunk($objects, 1000) as $chunk) {
200+
$this->client->deleteObjects([
201+
'Bucket' => $this->bucket,
202+
'Delete' => ['Objects' => $chunk],
203+
]);
204+
}
205+
} catch (\Throwable $e) {
206+
throw UnableToDeleteDirectory::atLocation($path, $e->getMessage(), $e);
198207
}
199208
}
200209

201210
public function createDirectory(string $path, Config $config): void
202211
{
203212
$defaultVisibility = $config->get(Config::OPTION_DIRECTORY_VISIBILITY, $this->visibility->defaultForDirectories());
204213
$config = $config->withDefaults([Config::OPTION_VISIBILITY => $defaultVisibility]);
205-
$this->upload(rtrim($path, '/') . '/', '', $config);
214+
215+
try {
216+
$this->upload(rtrim($path, '/') . '/', '', $config);
217+
} catch (Throwable $e) {
218+
throw UnableToCreateDirectory::dueToFailure($path, $e);
219+
}
206220
}
207221

208222
public function setVisibility(string $path, string $visibility): void
@@ -292,16 +306,20 @@ public function listContents(string $path, bool $deep): iterable
292306
$options['Delimiter'] = '/';
293307
}
294308

295-
$listing = $this->retrievePaginatedListing($options);
309+
try {
310+
$listing = $this->retrievePaginatedListing($options);
296311

297-
foreach ($listing as $item) {
298-
$item = $this->mapS3ObjectMetadata($item);
312+
foreach ($listing as $item) {
313+
$item = $this->mapS3ObjectMetadata($item);
299314

300-
if ($item->path() === $path) {
301-
continue;
302-
}
315+
if ($item->path() === $path) {
316+
continue;
317+
}
303318

304-
yield $item;
319+
yield $item;
320+
}
321+
} catch (\Throwable $e) {
322+
throw UnableToListContents::atLocation($path, $deep, $e);
305323
}
306324
}
307325

@@ -363,16 +381,20 @@ private function upload(string $path, $body, Config $config): void
363381
$options['ContentType'] = $mimeType;
364382
}
365383

366-
if ($this->client instanceof SimpleS3Client) {
367-
// Supports upload of files larger than 5GB
368-
$this->client->upload($this->bucket, $key, $body, array_merge($options, ['ACL' => $acl]));
369-
} else {
370-
$this->client->putObject(array_merge($options, [
371-
'Bucket' => $this->bucket,
372-
'Key' => $key,
373-
'Body' => $body,
374-
'ACL' => $acl,
375-
]));
384+
try {
385+
if ($this->client instanceof SimpleS3Client) {
386+
// Supports upload of files larger than 5GB
387+
$this->client->upload($this->bucket, $key, $body, array_merge($options, ['ACL' => $acl]));
388+
} else {
389+
$this->client->putObject(array_merge($options, [
390+
'Bucket' => $this->bucket,
391+
'Key' => $key,
392+
'Body' => $body,
393+
'ACL' => $acl,
394+
]));
395+
}
396+
} catch (Throwable $exception) {
397+
throw UnableToWriteFile::atLocation($path, $exception->getMessage(), $exception);
376398
}
377399
}
378400

src/AsyncAwsS3/AsyncAwsS3AdapterTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
use League\Flysystem\StorageAttributes;
2323
use League\Flysystem\UnableToCheckFileExistence;
2424
use League\Flysystem\UnableToDeleteFile;
25+
use League\Flysystem\UnableToListContents;
2526
use League\Flysystem\UnableToMoveFile;
2627
use League\Flysystem\UnableToRetrieveMetadata;
28+
use League\Flysystem\UnableToWriteFile;
2729
use League\Flysystem\Visibility;
2830
use function getenv;
2931
use function iterator_to_array;
@@ -324,6 +326,18 @@ public function write_with_simple_s3_client(): void
324326
$filesystem->write($file, $contents, new Config());
325327
}
326328

329+
/**
330+
* @test
331+
*/
332+
public function failing_to_write_a_file(): void
333+
{
334+
$adapter = $this->adapter();
335+
static::$stubS3Client->throwExceptionWhenExecutingCommand('PutObject');
336+
$this->expectException(UnableToWriteFile::class);
337+
338+
$adapter->write('foo/bar.txt', 'contents', new Config());
339+
}
340+
327341
/**
328342
* @test
329343
*/
@@ -392,6 +406,19 @@ public function top_level_directory_excluded_from_listing(): void
392406
});
393407
}
394408

409+
/**
410+
* @test
411+
*/
412+
public function failing_to_list_contents(): void
413+
{
414+
$adapter = $this->adapter();
415+
static::$stubS3Client->throwExceptionWhenExecutingCommand('ListObjectsV2');
416+
417+
$this->expectException(UnableToListContents::class);
418+
419+
iterator_to_array($adapter->listContents('/path', false));
420+
}
421+
395422
protected static function createFilesystemAdapter(): FilesystemAdapter
396423
{
397424
static::$stubS3Client = new S3ClientStub(static::s3Client(), self::awsConfig());

0 commit comments

Comments
 (0)