aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/lib/Command/DeleteOrphanedFiles.php
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files/lib/Command/DeleteOrphanedFiles.php')
-rw-r--r--apps/files/lib/Command/DeleteOrphanedFiles.php88
1 files changed, 62 insertions, 26 deletions
diff --git a/apps/files/lib/Command/DeleteOrphanedFiles.php b/apps/files/lib/Command/DeleteOrphanedFiles.php
index b7101c07258..8f93242b255 100644
--- a/apps/files/lib/Command/DeleteOrphanedFiles.php
+++ b/apps/files/lib/Command/DeleteOrphanedFiles.php
@@ -35,17 +35,18 @@ class DeleteOrphanedFiles extends Command {
public function execute(InputInterface $input, OutputInterface $output): int {
$deletedEntries = 0;
+ $fileIdsByStorage = [];
- $query = $this->connection->getQueryBuilder();
- $query->select('fc.fileid')
- ->from('filecache', 'fc')
- ->where($query->expr()->isNull('s.numeric_id'))
- ->leftJoin('fc', 'storages', 's', $query->expr()->eq('fc.storage', 's.numeric_id'))
- ->setMaxResults(self::CHUNK_SIZE);
+ $deletedStorages = array_diff($this->getReferencedStorages(), $this->getExistingStorages());
+
+ $deleteExtended = !$input->getOption('skip-filecache-extended');
+ if ($deleteExtended) {
+ $fileIdsByStorage = $this->getFileIdsForStorages($deletedStorages);
+ }
$deleteQuery = $this->connection->getQueryBuilder();
$deleteQuery->delete('filecache')
- ->where($deleteQuery->expr()->eq('fileid', $deleteQuery->createParameter('objectid')));
+ ->where($deleteQuery->expr()->in('storage', $deleteQuery->createParameter('storage_ids')));
$deletedInLastChunk = self::CHUNK_SIZE;
while ($deletedInLastChunk === self::CHUNK_SIZE) {
@@ -61,8 +62,8 @@ class DeleteOrphanedFiles extends Command {
$output->writeln("$deletedEntries orphaned file cache entries deleted");
- if (!$input->getOption('skip-filecache-extended')) {
- $deletedFileCacheExtended = $this->cleanupOrphanedFileCacheExtended();
+ if ($deleteExtended) {
+ $deletedFileCacheExtended = $this->cleanupOrphanedFileCacheExtended($fileIdsByStorage);
$output->writeln("$deletedFileCacheExtended orphaned file cache extended entries deleted");
}
@@ -72,28 +73,63 @@ class DeleteOrphanedFiles extends Command {
return self::SUCCESS;
}
- private function cleanupOrphanedFileCacheExtended(): int {
- $deletedEntries = 0;
-
+ private function getReferencedStorages(): array {
$query = $this->connection->getQueryBuilder();
- $query->select('fce.fileid')
- ->from('filecache_extended', 'fce')
- ->leftJoin('fce', 'filecache', 'fc', $query->expr()->eq('fce.fileid', 'fc.fileid'))
- ->where($query->expr()->isNull('fc.fileid'))
- ->setMaxResults(self::CHUNK_SIZE);
+ $query->select('storage')
+ ->from('filecache')
+ ->groupBy('storage')
+ ->runAcrossAllShards();
+ return $query->executeQuery()->fetchAll(\PDO::FETCH_COLUMN);
+ }
- $deleteQuery = $this->connection->getQueryBuilder();
- $deleteQuery->delete('filecache_extended')
- ->where($deleteQuery->expr()->in('fileid', $deleteQuery->createParameter('idsToDelete')));
+ private function getExistingStorages(): array {
+ $query = $this->connection->getQueryBuilder();
+ $query->select('numeric_id')
+ ->from('storages')
+ ->groupBy('numeric_id');
+ return $query->executeQuery()->fetchAll(\PDO::FETCH_COLUMN);
+ }
- $result = $query->executeQuery();
- while ($result->rowCount() > 0) {
- $idsToDelete = $result->fetchAll(\PDO::FETCH_COLUMN);
+ /**
+ * @param int[] $storageIds
+ * @return array<int, int[]>
+ */
+ private function getFileIdsForStorages(array $storageIds): array {
+ $query = $this->connection->getQueryBuilder();
+ $query->select('storage', 'fileid')
+ ->from('filecache')
+ ->where($query->expr()->in('storage', $query->createParameter('storage_ids')));
+
+ $result = [];
+ $storageIdChunks = array_chunk($storageIds, self::CHUNK_SIZE);
+ foreach ($storageIdChunks as $storageIdChunk) {
+ $query->setParameter('storage_ids', $storageIdChunk, IQueryBuilder::PARAM_INT_ARRAY);
+ $chunk = $query->executeQuery()->fetchAll();
+ foreach ($chunk as $row) {
+ $result[$row['storage']][] = $row['fileid'];
+ }
+ }
+ return $result;
+ }
- $deleteQuery->setParameter('idsToDelete', $idsToDelete, IQueryBuilder::PARAM_INT_ARRAY);
- $deletedEntries += $deleteQuery->executeStatement();
+ /**
+ * @param array<int, int[]> $fileIdsByStorage
+ * @return int
+ */
+ private function cleanupOrphanedFileCacheExtended(array $fileIdsByStorage): int {
+ $deletedEntries = 0;
- $result = $query->executeQuery();
+ $deleteQuery = $this->connection->getQueryBuilder();
+ $deleteQuery->delete('filecache_extended')
+ ->where($deleteQuery->expr()->in('fileid', $deleteQuery->createParameter('file_ids')));
+
+ foreach ($fileIdsByStorage as $storageId => $fileIds) {
+ $deleteQuery->hintShardKey('storage', $storageId, true);
+ $fileChunks = array_chunk($fileIds, self::CHUNK_SIZE);
+ foreach ($fileChunks as $fileChunk) {
+ $deleteQuery->setParameter('file_ids', $fileChunk, IQueryBuilder::PARAM_INT_ARRAY);
+ $deletedEntries += $deleteQuery->executeStatement();
+ }
}
return $deletedEntries;