Skip to content

Commit c08a4d4

Browse files
committed
feat: add concurrent uploads for uploads:import command
1 parent d01dd44 commit c08a4d4

1 file changed

Lines changed: 18 additions & 71 deletions

File tree

src/Command/Uploads/ImportUploadsCommand.php

Lines changed: 18 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,6 @@ class ImportUploadsCommand extends AbstractProjectCommand
4545
*/
4646
public const NAME = 'uploads:import';
4747

48-
/**
49-
* The temporary directory used for importing.
50-
*
51-
* @var string
52-
*/
53-
private $tempDirectory;
54-
5548
/**
5649
* The uploader used to upload files.
5750
*
@@ -69,25 +62,6 @@ public function __construct(ApiClient $apiClient, CliConfiguration $cliConfigura
6962
$this->uploader = $uploader;
7063
}
7164

72-
/**
73-
* Delete the temporary directory when we're done the execution.
74-
*/
75-
public function __destruct()
76-
{
77-
if (!is_string($this->tempDirectory) || !is_dir($this->tempDirectory)) {
78-
return;
79-
}
80-
81-
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->tempDirectory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST);
82-
83-
foreach ($files as $file) {
84-
$function = $file->isDir() ? 'rmdir' : 'unlink';
85-
$function($file->getRealPath());
86-
}
87-
88-
rmdir($this->tempDirectory);
89-
}
90-
9165
/**
9266
* {@inheritdoc}
9367
*/
@@ -99,17 +73,24 @@ protected function configure()
9973
->addArgument('path', InputArgument::REQUIRED, 'The path to the files to import')
10074
->addOption('environment', null, InputOption::VALUE_REQUIRED, 'The environment to upload files to', 'staging')
10175
->addOption('force', null, InputOption::VALUE_NONE, 'Force the import to run')
102-
->addOption('size', null, InputOption::VALUE_REQUIRED, 'The number of files to process at a time', '20');
76+
->addOption('size', null, InputOption::VALUE_REQUIRED, 'The number of files to process at a time');
10377
}
10478

10579
/**
10680
* {@inheritdoc}
10781
*/
10882
protected function perform(InputInterface $input, OutputInterface $output)
10983
{
84+
$adapter = $this->getAdapter($this->getStringArgument($input, 'path'));
11085
$environment = (string) $this->getStringOption($input, 'environment');
111-
$filesystem = new Filesystem($this->getAdapter($this->getStringArgument($input, 'path')));
112-
$size = (int) $this->getNumericOption($input, 'size');
86+
$filesystem = new Filesystem($adapter);
87+
$size = $this->getNumericOption($input, 'size');
88+
89+
if (null === $size && $adapter instanceof LocalFilesystemAdapter) {
90+
$size = 1000;
91+
} elseif (null === $size) {
92+
$size = 100;
93+
}
11394

11495
if ($size < 1) {
11596
throw new InvalidArgumentException('Cannot have a "size" smaller than 1');
@@ -119,8 +100,6 @@ protected function perform(InputInterface $input, OutputInterface $output)
119100
return;
120101
}
121102

122-
$this->tempDirectory = $this->createTempDirectory();
123-
124103
$output->info(sprintf('Starting file import to the "<comment>%s</comment>" environment "uploads" directory', $environment));
125104

126105
$progressBar = new ProgressBar($output);
@@ -129,7 +108,7 @@ protected function perform(InputInterface $input, OutputInterface $output)
129108
$total = 0;
130109
$progressBar->setMessage((string) $total, 'total');
131110

132-
LazyCollection::make(function () use ($filesystem) {
111+
$requests = LazyCollection::make(function () use ($filesystem) {
133112
$files = $filesystem->listContents('', Filesystem::LIST_DEEP)->filter(function (StorageAttributes $attributes) {
134113
return $attributes->isFile();
135114
});
@@ -139,53 +118,21 @@ protected function perform(InputInterface $input, OutputInterface $output)
139118
}
140119
})->chunk($size)->mapWithKeys(function (Enumerable $chunkedFiles) use ($environment) {
141120
return $this->getSignedUploadRequest($environment, $chunkedFiles);
142-
})->each(function (array $request, string $filePath) use ($filesystem, $progressBar, &$total) {
143-
$tempFilePath = $this->tempDirectory.'/'.basename($filePath);
144-
145-
$progressBar->setMessage($filePath, 'filename');
146-
$progressBar->advance();
147-
148-
file_put_contents($tempFilePath, $filesystem->readStream($filePath));
149-
150-
$this->uploader->uploadFile($tempFilePath, $request['uri'], $request['headers']);
151-
152-
unlink($tempFilePath);
121+
})->map(function (array $request, string $filePath) use ($filesystem, $progressBar, &$total) {
122+
$request['body'] = $filesystem->readStream($filePath);
153123

154124
++$total;
155125

126+
$progressBar->setMessage($filePath, 'filename');
156127
$progressBar->setMessage((string) $total, 'total');
157128
$progressBar->advance();
158-
});
159-
160-
$output->info(sprintf('Files imported successfully to the "<comment>%s</comment>" environment "uploads" directory', $environment));
161-
}
162129

163-
/**
164-
* Create a temporary directory to copy over files temporarily.
165-
*/
166-
private function createTempDirectory(): string
167-
{
168-
$baseDirectory = sys_get_temp_dir().'/';
169-
$maxAttempts = 100;
170-
171-
if (!is_dir($baseDirectory)) {
172-
throw new RuntimeException(sprintf('"%s" isn\'t a directory', $baseDirectory));
173-
} elseif (!is_writable($baseDirectory)) {
174-
throw new RuntimeException(sprintf('"%s" isn\'t writable', $baseDirectory));
175-
}
176-
177-
$attempts = 0;
130+
return $request;
131+
});
178132

179-
do {
180-
++$attempts;
181-
$tmpDirectory = sprintf('%s%s%s', $baseDirectory, 'ymir_', mt_rand(100000, mt_getrandmax()));
182-
} while (!mkdir($tmpDirectory) && $attempts < $maxAttempts);
133+
$this->uploader->batch('PUT', $requests);
183134

184-
if (!is_dir($tmpDirectory)) {
185-
throw new RuntimeException('Failed to create a temporary directory');
186-
}
187-
188-
return $tmpDirectory;
135+
$output->info(sprintf('Files imported successfully to the "<comment>%s</comment>" environment "uploads" directory', $environment));
189136
}
190137

191138
/**

0 commit comments

Comments
 (0)