|
8 | 8 | */ |
9 | 9 | namespace OCA\DAV\Migration; |
10 | 10 |
|
11 | | -use OCA\DAV\CalDAV\CalDavBackend; |
12 | | -use OCP\DB\QueryBuilder\IQueryBuilder; |
13 | | -use OCP\IDBConnection; |
| 11 | +use OCA\DAV\BackgroundJob\CleanupOrphanedChildrenJob; |
| 12 | +use OCP\BackgroundJob\IJobList; |
14 | 13 | use OCP\Migration\IOutput; |
15 | 14 | use OCP\Migration\IRepairStep; |
16 | 15 |
|
17 | 16 | class RemoveOrphanEventsAndContacts implements IRepairStep { |
18 | | - |
19 | | - /** @var IDBConnection */ |
20 | | - private $connection; |
21 | | - |
22 | | - public function __construct(IDBConnection $connection) { |
23 | | - $this->connection = $connection; |
| 17 | + public function __construct( |
| 18 | + private readonly IJobList $jobList, |
| 19 | + ) { |
24 | 20 | } |
25 | 21 |
|
26 | | - /** |
27 | | - * @inheritdoc |
28 | | - */ |
29 | 22 | public function getName(): string { |
30 | | - return 'Clean up orphan event and contact data'; |
| 23 | + return 'Queue jobs to clean up orphan event and contact data'; |
31 | 24 | } |
32 | 25 |
|
33 | | - /** |
34 | | - * @inheritdoc |
35 | | - */ |
36 | | - public function run(IOutput $output) { |
37 | | - $orphanItems = $this->removeOrphanChildren('calendarobjects', 'calendars', 'calendarid'); |
38 | | - $output->info(sprintf('%d events without a calendar have been cleaned up', $orphanItems)); |
39 | | - $orphanItems = $this->removeOrphanChildren('calendarobjects_props', 'calendarobjects', 'objectid'); |
40 | | - $output->info(sprintf('%d properties without an events have been cleaned up', $orphanItems)); |
41 | | - $orphanItems = $this->removeOrphanChildren('calendarchanges', 'calendars', 'calendarid'); |
42 | | - $output->info(sprintf('%d changes without a calendar have been cleaned up', $orphanItems)); |
| 26 | + public function run(IOutput $output): void { |
| 27 | + $this->queueJob('calendarobjects', 'calendars', 'calendarid', '%d events without a calendar have been cleaned up'); |
| 28 | + $this->queueJob('calendarobjects_props', 'calendarobjects', 'objectid', '%d properties without an events have been cleaned up'); |
| 29 | + $this->queueJob('calendarchanges', 'calendars', 'calendarid', '%d changes without a calendar have been cleaned up'); |
43 | 30 |
|
44 | | - $orphanItems = $this->removeOrphanChildren('calendarobjects', 'calendarsubscriptions', 'calendarid'); |
45 | | - $output->info(sprintf('%d cached events without a calendar subscription have been cleaned up', $orphanItems)); |
46 | | - $orphanItems = $this->removeOrphanChildren('calendarchanges', 'calendarsubscriptions', 'calendarid'); |
47 | | - $output->info(sprintf('%d changes without a calendar subscription have been cleaned up', $orphanItems)); |
| 31 | + $this->queueJob('calendarobjects', 'calendarsubscriptions', 'calendarid', '%d cached events without a calendar subscription have been cleaned up'); |
| 32 | + $this->queueJob('calendarchanges', 'calendarsubscriptions', 'calendarid', '%d changes without a calendar subscription have been cleaned up'); |
48 | 33 |
|
49 | | - $orphanItems = $this->removeOrphanChildren('cards', 'addressbooks', 'addressbookid'); |
50 | | - $output->info(sprintf('%d contacts without an addressbook have been cleaned up', $orphanItems)); |
51 | | - $orphanItems = $this->removeOrphanChildren('cards_properties', 'cards', 'cardid'); |
52 | | - $output->info(sprintf('%d properties without a contact have been cleaned up', $orphanItems)); |
53 | | - $orphanItems = $this->removeOrphanChildren('addressbookchanges', 'addressbooks', 'addressbookid'); |
54 | | - $output->info(sprintf('%d changes without an addressbook have been cleaned up', $orphanItems)); |
| 34 | + $this->queueJob('cards', 'addressbooks', 'addressbookid', '%d contacts without an addressbook have been cleaned up'); |
| 35 | + $this->queueJob('cards_properties', 'cards', 'cardid', '%d properties without a contact have been cleaned up'); |
| 36 | + $this->queueJob('addressbookchanges', 'addressbooks', 'addressbookid', '%d changes without an addressbook have been cleaned up'); |
55 | 37 | } |
56 | 38 |
|
57 | | - protected function removeOrphanChildren($childTable, $parentTable, $parentId): int { |
58 | | - $qb = $this->connection->getQueryBuilder(); |
59 | | - |
60 | | - $qb->select('c.id') |
61 | | - ->from($childTable, 'c') |
62 | | - ->leftJoin('c', $parentTable, 'p', $qb->expr()->eq('c.' . $parentId, 'p.id')) |
63 | | - ->where($qb->expr()->isNull('p.id')); |
64 | | - |
65 | | - if (\in_array($parentTable, ['calendars', 'calendarsubscriptions'], true)) { |
66 | | - $calendarType = $parentTable === 'calendarsubscriptions' ? CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION : CalDavBackend::CALENDAR_TYPE_CALENDAR; |
67 | | - $qb->andWhere($qb->expr()->eq('c.calendartype', $qb->createNamedParameter($calendarType, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)); |
68 | | - } |
69 | | - |
70 | | - $result = $qb->execute(); |
71 | | - |
72 | | - $orphanItems = []; |
73 | | - while ($row = $result->fetch()) { |
74 | | - $orphanItems[] = (int) $row['id']; |
75 | | - } |
76 | | - $result->closeCursor(); |
77 | | - |
78 | | - if (!empty($orphanItems)) { |
79 | | - $qb->delete($childTable) |
80 | | - ->where($qb->expr()->in('id', $qb->createParameter('ids'))); |
81 | | - |
82 | | - $orphanItemsBatch = array_chunk($orphanItems, 1000); |
83 | | - foreach ($orphanItemsBatch as $items) { |
84 | | - $qb->setParameter('ids', $items, IQueryBuilder::PARAM_INT_ARRAY); |
85 | | - $qb->execute(); |
86 | | - } |
87 | | - } |
88 | | - |
89 | | - return count($orphanItems); |
| 39 | + private function queueJob( |
| 40 | + string $childTable, |
| 41 | + string $parentTable, |
| 42 | + string $parentId, |
| 43 | + string $logMessage, |
| 44 | + ): void { |
| 45 | + $this->jobList->add(CleanupOrphanedChildrenJob::class, [ |
| 46 | + CleanupOrphanedChildrenJob::ARGUMENT_CHILD_TABLE => $childTable, |
| 47 | + CleanupOrphanedChildrenJob::ARGUMENT_PARENT_TABLE => $parentTable, |
| 48 | + CleanupOrphanedChildrenJob::ARGUMENT_PARENT_ID => $parentId, |
| 49 | + CleanupOrphanedChildrenJob::ARGUMENT_LOG_MESSAGE => $logMessage, |
| 50 | + ]); |
90 | 51 | } |
91 | 52 | } |
0 commit comments