@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Destroy file attachments when file is deleted, or object is deleted

Summary:
Adds file attachment deletion logics:

- PhabricatorFile: delete the attachment if file is deleted
- destruction engine extension: delete attachment if object is deleted
- SQL patch: delete existing leftover attachments from deleted files

To apply the cleanup, as usual, run:

./bin/storage upgrade

This cleanup may take some time, proportionally to the size of these tables:

phabricator_file.file
phabricator_file.file_attachment

Just as an indication: the storage upgrade, in a Phorge with `file` count 1.3M rows and `file_attachment` consisting in 9K rows, it may delete 170K rows in less than 1 second on average hardware.

Closes T15110

Test Plan:
Apply the patch, run `./bin/storage/upgrade`:

- no "Unknown Object" in any "Referenced Files" curtain of any object.

Have phd daemon running.

Upload file, attach the file to a task, delete the file from the web interface:

- no "Unknown Object" in "Referenced Files" curtain of that task.
- the query `SELECT * FROM file_attachment WHERE filePHID = '<file phid>'` returns empty result

Upload file, attach the file to a task, delete the task from the `./bin/remove destroy` workflow:

- the query `SELECT * FROM file_attachment WHERE objectPHID = '<task phid>'` returns empty result

Reviewers: O1 Blessed Committers, avivey, valerio.bozzolan

Reviewed By: O1 Blessed Committers, avivey, valerio.bozzolan

Subscribers: Ekubischta, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno

Tags: #files

Maniphest Tasks: T15110

Differential Revision: https://we.phorge.it/D25051

authored by

Dylan F and committed by
Valerio Bozzolan
2b7c0ec9 b74f1ad5

+38
+6
resources/sql/autopatches/20230917.fileattachment.01.delete.sql
··· 1 + USE {$NAMESPACE}_file; 2 + DELETE FROM file_attachment 3 + WHERE NOT EXISTS 4 + (SELECT * 5 + FROM file 6 + WHERE phid=file_attachment.filePHID)
+2
src/__phutil_library_map__.php
··· 3453 3453 'PhabricatorFileAES256StorageFormat' => 'applications/files/format/PhabricatorFileAES256StorageFormat.php', 3454 3454 'PhabricatorFileAltTextTransaction' => 'applications/files/xaction/PhabricatorFileAltTextTransaction.php', 3455 3455 'PhabricatorFileAttachment' => 'applications/files/storage/PhabricatorFileAttachment.php', 3456 + 'PhabricatorFileAttachmentDestructionEngineExtension' => 'applications/files/engineextension/PhabricatorFileAttachmentDestructionEngineExtension.php', 3456 3457 'PhabricatorFileAttachmentQuery' => 'applications/files/query/PhabricatorFileAttachmentQuery.php', 3457 3458 'PhabricatorFileBundleLoader' => 'applications/files/query/PhabricatorFileBundleLoader.php', 3458 3459 'PhabricatorFileChunk' => 'applications/files/storage/PhabricatorFileChunk.php', ··· 9924 9925 'PhabricatorPolicyInterface', 9925 9926 'PhabricatorExtendedPolicyInterface', 9926 9927 ), 9928 + 'PhabricatorFileAttachmentDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 9927 9929 'PhabricatorFileAttachmentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 9928 9930 'PhabricatorFileBundleLoader' => 'Phobject', 9929 9931 'PhabricatorFileChunk' => array(
+22
src/applications/files/engineextension/PhabricatorFileAttachmentDestructionEngineExtension.php
··· 1 + <?php 2 + 3 + final class PhabricatorFileAttachmentDestructionEngineExtension 4 + extends PhabricatorDestructionEngineExtension { 5 + 6 + const EXTENSIONKEY = 'file.attachments'; 7 + 8 + public function getExtensionName() { 9 + return pht('File Attachments'); 10 + } 11 + 12 + public function destroyObject( 13 + PhabricatorDestructionEngine $engine, 14 + $object) { 15 + $attachments = id(new PhabricatorFileAttachment())->loadAllWhere( 16 + 'objectPHID = %s', 17 + $object->getPHID()); 18 + foreach ($attachments as $attachment) { 19 + $attachment->delete(); 20 + } 21 + } 22 + }
+8
src/applications/files/storage/PhabricatorFile.php
··· 1785 1785 PhabricatorDestructionEngine $engine) { 1786 1786 1787 1787 $this->openTransaction(); 1788 + 1789 + $attachments = id(new PhabricatorFileAttachment())->loadAllWhere( 1790 + 'filePHID = %s', 1791 + $this->getPHID()); 1792 + foreach ($attachments as $attachment) { 1793 + $attachment->delete(); 1794 + } 1795 + 1788 1796 $this->delete(); 1789 1797 $this->saveTransaction(); 1790 1798 }