diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/App/AppManager.php | 2 | ||||
-rw-r--r-- | lib/private/Files/FilenameValidator.php | 2 | ||||
-rw-r--r-- | lib/private/Files/ObjectStore/S3ObjectTrait.php | 60 | ||||
-rw-r--r-- | lib/public/App/IAppManager.php | 2 | ||||
-rw-r--r-- | lib/public/Files/IFilenameValidator.php | 2 |
5 files changed, 47 insertions, 21 deletions
diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index 4223d09e3dc..303a88e9ceb 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -204,7 +204,7 @@ class AppManager implements IAppManager { * List all apps enabled for a user * * @param \OCP\IUser $user - * @return string[] + * @return list<string> */ public function getEnabledAppsForUser(IUser $user) { $apps = $this->getEnabledAppsValues(); diff --git a/lib/private/Files/FilenameValidator.php b/lib/private/Files/FilenameValidator.php index 57a62b0b219..a78c6d3cc3c 100644 --- a/lib/private/Files/FilenameValidator.php +++ b/lib/private/Files/FilenameValidator.php @@ -232,7 +232,7 @@ class FilenameValidator implements IFilenameValidator { $forbiddenCharacters = $this->getForbiddenCharacters(); if ($charReplacement === null) { - $charReplacement = array_diff([' ', '_', '-'], $forbiddenCharacters); + $charReplacement = array_diff(['_', '-', ' '], $forbiddenCharacters); $charReplacement = reset($charReplacement) ?: ''; } if (mb_strlen($charReplacement) !== 1) { diff --git a/lib/private/Files/ObjectStore/S3ObjectTrait.php b/lib/private/Files/ObjectStore/S3ObjectTrait.php index 61e8158b863..5e6dcf88a42 100644 --- a/lib/private/Files/ObjectStore/S3ObjectTrait.php +++ b/lib/private/Files/ObjectStore/S3ObjectTrait.php @@ -119,28 +119,54 @@ trait S3ObjectTrait { protected function writeMultiPart(string $urn, StreamInterface $stream, array $metaData): void { $mimetype = $metaData['mimetype'] ?? null; unset($metaData['mimetype']); - $uploader = new MultipartUploader($this->getConnection(), $stream, [ - 'bucket' => $this->bucket, - 'concurrency' => $this->concurrency, - 'key' => $urn, - 'part_size' => $this->uploadPartSize, - 'params' => [ - 'ContentType' => $mimetype, - 'Metadata' => $this->buildS3Metadata($metaData), - 'StorageClass' => $this->storageClass, - ] + $this->getSSECParameters(), - ]); - try { - $uploader->upload(); - } catch (S3MultipartUploadException $e) { + $attempts = 0; + $uploaded = false; + $concurrency = $this->concurrency; + $exception = null; + $state = null; + + // retry multipart upload once with concurrency at half on failure + while (!$uploaded && $attempts <= 1) { + $uploader = new MultipartUploader($this->getConnection(), $stream, [ + 'bucket' => $this->bucket, + 'concurrency' => $concurrency, + 'key' => $urn, + 'part_size' => $this->uploadPartSize, + 'state' => $state, + 'params' => [ + 'ContentType' => $mimetype, + 'Metadata' => $this->buildS3Metadata($metaData), + 'StorageClass' => $this->storageClass, + ] + $this->getSSECParameters(), + ]); + + try { + $uploader->upload(); + $uploaded = true; + } catch (S3MultipartUploadException $e) { + $exception = $e; + $attempts++; + + if ($concurrency > 1) { + $concurrency = round($concurrency / 2); + } + + if ($stream->isSeekable()) { + $stream->rewind(); + } + } + } + + if (!$uploaded) { // if anything goes wrong with multipart, make sure that you don“t poison and // slow down s3 bucket with orphaned fragments - $uploadInfo = $e->getState()->getId(); - if ($e->getState()->isInitiated() && (array_key_exists('UploadId', $uploadInfo))) { + $uploadInfo = $exception->getState()->getId(); + if ($exception->getState()->isInitiated() && (array_key_exists('UploadId', $uploadInfo))) { $this->getConnection()->abortMultipartUpload($uploadInfo); } - throw new \OCA\DAV\Connector\Sabre\Exception\BadGateway('Error while uploading to S3 bucket', 0, $e); + + throw new \OCA\DAV\Connector\Sabre\Exception\BadGateway('Error while uploading to S3 bucket', 0, $exception); } } diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php index 6eae870216f..20019ce1ffd 100644 --- a/lib/public/App/IAppManager.php +++ b/lib/public/App/IAppManager.php @@ -184,7 +184,7 @@ interface IAppManager { * List all apps enabled for a user * * @param \OCP\IUser $user - * @return string[] + * @return list<string> * @since 8.1.0 */ public function getEnabledAppsForUser(IUser $user); diff --git a/lib/public/Files/IFilenameValidator.php b/lib/public/Files/IFilenameValidator.php index d8bd06d179d..9b7fa1e2e2e 100644 --- a/lib/public/Files/IFilenameValidator.php +++ b/lib/public/Files/IFilenameValidator.php @@ -43,7 +43,7 @@ interface IFilenameValidator { * If no sanitizing is needed the same name is returned. * * @param string $name The filename to sanitize - * @param null|string $charReplacement Character to use for replacing forbidden ones - by default space, dash or underscore is used if allowed. + * @param null|string $charReplacement Character to use for replacing forbidden ones - by default underscore, dash or space is used if allowed. * @throws \InvalidArgumentException if no character replacement was given (and the default could not be applied) or the replacement is not valid. * @since 32.0.0 */ |