PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / trunk
JetBackup – Backup, Restore & Migrate vtrunk
3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / Cron / Task / RetentionCleanup.php
backup / src / JetBackup / Cron / Task Last commit date
.htaccess 1 year ago Backup.php 1 year ago Download.php 1 year ago DownloadBackupLog.php 1 year ago Export.php 1 year ago Extract.php 1 year ago PreRestore.php 5 months ago Reindex.php 2 months ago Restore.php 5 months ago RetentionCleanup.php 4 months ago System.php 6 months ago Task.php 4 months ago index.html 1 year ago web.config 1 year ago
RetentionCleanup.php
247 lines
1 <?php
2
3 namespace JetBackup\Cron\Task;
4
5 use JetBackup\Data\Engine;
6 use JetBackup\Destination\Destination;
7 use JetBackup\Destination\Vendors\Imported\Imported;
8 use JetBackup\Exception\DBException;
9 use JetBackup\Exception\TaskException;
10 use JetBackup\Factory;
11 use JetBackup\JetBackup;
12 use JetBackup\Queue\Queue;
13 use JetBackup\Queue\QueueItem;
14 use JetBackup\Schedule\Schedule;
15 use JetBackup\Snapshot\Snapshot;
16 use SleekDB\Exceptions\InvalidArgumentException;
17 use SleekDB\Exceptions\IOException;
18
19 if (!defined( '__JETBACKUP__')) die('Direct access is not allowed');
20
21 class RetentionCleanup extends Task {
22
23 const LOG_FILENAME = 'retention';
24
25 public function __construct() {
26 parent::__construct(self::LOG_FILENAME);
27 }
28
29 /**
30 * @return void
31 * @throws TaskException
32 * @throws IOException
33 * @throws InvalidArgumentException
34 */
35 public function execute():void {
36 parent::execute();
37
38 if($this->getQueueItem()->getStatus() == Queue::STATUS_PENDING) {
39 $this->getLogController()->logMessage("Starting snapshots retention cleanup");
40
41 $this->getQueueItem()->getProgress()->setTotalItems(count(Queue::STATUS_CLEANUP_NAMES)+3);
42 $this->getQueueItem()->save();
43 $this->getQueueItem()->updateProgress('Starting cleanup');
44 } else if($this->getQueueItem()->getStatus() > Queue::STATUS_PENDING) {
45 $this->getLogController()->logMessage('Resumed snapshots retention cleanup');
46 }
47
48 try {
49 $this->func([$this, '_markManualSnapshots']);
50 $this->func([$this, '_markImportedSnapshots']);
51 $this->func([$this, '_deleteSnapshots']);
52 if($this->getQueueItem()->getStatus() < Queue::STATUS_DONE && !$this->getQueueItem()->getErrors()) $this->getQueueItem()->updateStatus(Queue::STATUS_DONE);
53 else $this->getQueueItem()->updateStatus(Queue::STATUS_PARTIALLY);
54 $this->getLogController()->logMessage('Completed!');
55 } catch(\Exception $e) {
56 $this->getLogController()->logError($e->getMessage());
57 $this->getQueueItem()->addError();
58 $this->getQueueItem()->updateStatus(Queue::STATUS_PARTIALLY);
59 }
60
61 $this->getQueueItem()->updateProgress(
62 $this->getQueueItem()->getStatus() == Queue::STATUS_DONE
63 ? 'Cleanup Completed!'
64 : ($this->getQueueItem()->getStatus() == Queue::STATUS_PARTIALLY
65 ? 'Completed with errors (see logs)'
66 : 'Cleanup Failed!'),
67 QueueItem::PROGRESS_LAST_STEP
68 );
69
70 $this->getLogController()->logMessage('Total time: ' . $this->getExecutionTimeElapsed());
71 }
72
73 /**
74 * get a list of manual snapshots limit results based on retention limit
75 *
76 * @param int $destinationID
77 *
78 * @return array
79 * @throws IOException
80 * @throws InvalidArgumentException
81 */
82 static public function getManualSnapshots(int $destinationID): array {
83
84 return Snapshot::query()
85 ->where([Snapshot::SCHEDULES, 'contains', Schedule::TYPE_MANUALLY])
86 ->where([Engine::ENGINE, '=', Engine::ENGINE_WP])
87 ->where([Snapshot::DESTINATION_ID, '=', $destinationID])
88 ->orderBy([Snapshot::CREATED => 'desc'])
89 ->skip(Factory::getSettingsGeneral()->getManualBackupsRetention())
90 ->getQuery()
91 ->fetch();
92 }
93
94 /**
95 * Mark manual snapshots for deletion per retention global settings
96 * @return void
97 * @throws IOException
98 * @throws InvalidArgumentException
99 * @throws DBException
100 */
101 public function _markManualSnapshots(): void {
102
103 if (!Factory::getSettingsGeneral()->getManualBackupsRetention()) {
104 $this->getLogController()->logMessage('[_markManualSnapshots] Manual Backups retention disabled, skipping');
105 return;
106 }
107
108 $this->getLogController()->logMessage('[_markManualSnapshots] Execution time: ' . $this->getExecutionTimeElapsed());
109 $this->getLogController()->logMessage('[_markManualSnapshots] TTL time: ' . $this->getExecutionTimeLimit());
110
111 $destinations = Destination::query()->select([JetBackup::ID_FIELD])->getQuery()->fetch();
112 foreach($destinations as $id) {
113
114 $destination = new Destination($id[JetBackup::ID_FIELD]);
115 if (!$destination->getId()) continue;
116 if (!$destination->isEnabled()) continue;
117 if ($destination->isReadOnly()) continue;
118
119 foreach(self::getManualSnapshots($destination->getId()) as $snapshot_details) {
120 $snapshot = new Snapshot($snapshot_details[JetBackup::ID_FIELD]);
121 $this->getLogController()->logDebug('Marking Manual snapshot for delete: ' . $snapshot->getName() . ' ' . $snapshot->getDestinationName() . ' [ID ' . $snapshot->getDestinationId() . ']');
122 $snapshot->removeSchedule(Schedule::TYPE_MANUALLY);
123 // if there is no more schedules assigned for this snapshot we need to delete it
124 if(!sizeof($snapshot->getSchedules())) $snapshot->setDeleted(time());
125 $snapshot->save();
126 }
127
128 }
129
130 }
131
132 /**
133 * Get a list of imported snapshots beyond the retention limit
134 *
135 * @return array
136 * @throws IOException
137 * @throws InvalidArgumentException
138 * @throws DBException
139 */
140 static public function getImportedSnapshots(): array {
141
142 $retentionLimit = Factory::getSettingsGeneral()->getImportedBackupsRetention();
143 if (!$retentionLimit) return []; // 0 means disabled
144
145 $importedDest = Destination::getImportedDestination();
146 if (!$importedDest) return [];
147
148 return Snapshot::query()
149 ->where([Snapshot::SCHEDULES, 'contains', Schedule::TYPE_IMPORTED])
150 ->where([Engine::ENGINE, '=', Engine::ENGINE_WP])
151 ->where([Snapshot::DESTINATION_ID, '=', $importedDest->getId()])
152 ->orderBy([Snapshot::CREATED => 'desc'])
153 ->skip($retentionLimit)
154 ->getQuery()
155 ->fetch();
156 }
157
158 /**
159 * Mark imported snapshots for deletion per retention limit
160 * @return void
161 * @throws IOException
162 * @throws InvalidArgumentException
163 * @throws DBException
164 */
165 public function _markImportedSnapshots(): void {
166
167 if (!Factory::getSettingsGeneral()->getImportedBackupsRetention()) {
168 $this->getLogController()->logMessage('[_markImportedSnapshots] Imported Backups retention disabled, skipping');
169 return;
170 }
171
172 $this->getLogController()->logMessage('[_markImportedSnapshots] Execution time: ' . $this->getExecutionTimeElapsed());
173 $this->getLogController()->logMessage('[_markImportedSnapshots] TTL time: ' . $this->getExecutionTimeLimit());
174
175 $importedDest = Destination::getImportedDestination();
176 if (!$importedDest) {
177 $this->getLogController()->logMessage('[_markImportedSnapshots] No imported destination found, skipping');
178 return;
179 }
180
181 foreach(self::getImportedSnapshots() as $snapshot_details) {
182 $snapshot = new Snapshot($snapshot_details[JetBackup::ID_FIELD]);
183 $this->getLogController()->logDebug('Marking Imported snapshot for delete: ' . $snapshot->getName() . ' ' . $snapshot->getDestinationName() . ' [ID ' . $snapshot->getDestinationId() . ']');
184 $snapshot->removeSchedule(Schedule::TYPE_IMPORTED);
185 $snapshot->removeSchedule(Schedule::TYPE_MANUALLY);
186 // if there is no more schedules assigned for this snapshot we need to delete it
187 if(!sizeof($snapshot->getSchedules())) $snapshot->setDeleted(time());
188 $snapshot->save();
189 }
190
191 }
192
193 /**
194 * @return array
195 * @throws IOException
196 * @throws InvalidArgumentException
197 */
198 static public function listSnapshots(): array {
199
200 return Snapshot::query()
201 ->where([Snapshot::DELETED, '>', 0])
202 ->where([Snapshot::DELETED, '<=', time()])
203 ->where([Engine::ENGINE, '=', Engine::ENGINE_WP])
204 ->orderBy([Snapshot::DESTINATION_ID => 'asc'])
205 ->getQuery()
206 ->fetch();
207
208 }
209
210 /**
211 * @return void
212 */
213 public function _deleteSnapshots() {
214
215
216 $this->getLogController()->logMessage('[_deleteSnapshots] Execution time: ' . $this->getExecutionTimeElapsed());
217 $this->getLogController()->logMessage('[_deleteSnapshots] TTL time: ' . $this->getExecutionTimeLimit());
218
219 $this->getQueueItem()->updateStatus(Queue::STATUS_CLEANUP_DELETING);
220 $this->getQueueItem()->updateProgress('Deleting snapshots');
221
222 $destinations = [];
223
224 $this->foreachCallable(['JetBackup\Cron\Task\RetentionCleanup', 'listSnapshots'], [], function($i, $snapshot_details) use ($destinations) {
225
226 try {
227 $snapshot = new Snapshot($snapshot_details[JetBackup::ID_FIELD]);
228
229 if(!isset($destinations[$snapshot->getDestinationId()]))
230 $destinations[$snapshot->getDestinationId()] = new Destination($snapshot->getDestinationId());
231
232 $destination = $destinations[$snapshot->getDestinationId()];
233
234 $this->getLogController()->logMessage("Deleting snapshot \"{$snapshot->getName()}\" from destination \"{$destination->getName()}\"");
235 $destination->removeDir($snapshot->getJobIdentifier() . '/' . $snapshot->getName());
236 $snapshot->delete();
237 } catch (\Exception $e) {
238 $this->getLogController()->logError("Error deleting snapshot \"{$snapshot->getName()}\" from destination \"{$destination->getName()}\"");
239 $this->getLogController()->logError($e->getMessage());
240 $this->getQueueItem()->addError();
241 return;
242 }
243
244
245 });
246 }
247 }