mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-31 00:48:21 +01:00
Make daemons perform file deletion
Summary: Deletion is a possibly time-intensive process, especially with large files that are backed by high-latency, chunked storage (such as S3). Even ~200mb objects take minutes to delete, which makes for an unhappy experience. Fixes T10828. Test Plan: Delete a large file, and stare in awe of the swiftness with which I am redirected to the main file application. Reviewers: #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: thoughtpolice, Korvin Maniphest Tasks: T10828 Differential Revision: https://secure.phabricator.com/D15743
This commit is contained in:
parent
e187519f00
commit
be00264ae7
10 changed files with 69 additions and 4 deletions
2
resources/sql/autopatches/20170418.files.isDeleted.sql
Normal file
2
resources/sql/autopatches/20170418.files.isDeleted.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_file.file
|
||||||
|
ADD isDeleted BOOL NOT NULL DEFAULT 0;
|
|
@ -1098,6 +1098,7 @@ phutil_register_library_map(array(
|
||||||
'FileAllocateConduitAPIMethod' => 'applications/files/conduit/FileAllocateConduitAPIMethod.php',
|
'FileAllocateConduitAPIMethod' => 'applications/files/conduit/FileAllocateConduitAPIMethod.php',
|
||||||
'FileConduitAPIMethod' => 'applications/files/conduit/FileConduitAPIMethod.php',
|
'FileConduitAPIMethod' => 'applications/files/conduit/FileConduitAPIMethod.php',
|
||||||
'FileCreateMailReceiver' => 'applications/files/mail/FileCreateMailReceiver.php',
|
'FileCreateMailReceiver' => 'applications/files/mail/FileCreateMailReceiver.php',
|
||||||
|
'FileDeletionWorker' => 'applications/files/worker/FileDeletionWorker.php',
|
||||||
'FileDownloadConduitAPIMethod' => 'applications/files/conduit/FileDownloadConduitAPIMethod.php',
|
'FileDownloadConduitAPIMethod' => 'applications/files/conduit/FileDownloadConduitAPIMethod.php',
|
||||||
'FileInfoConduitAPIMethod' => 'applications/files/conduit/FileInfoConduitAPIMethod.php',
|
'FileInfoConduitAPIMethod' => 'applications/files/conduit/FileInfoConduitAPIMethod.php',
|
||||||
'FileMailReceiver' => 'applications/files/mail/FileMailReceiver.php',
|
'FileMailReceiver' => 'applications/files/mail/FileMailReceiver.php',
|
||||||
|
@ -5977,6 +5978,7 @@ phutil_register_library_map(array(
|
||||||
'FileAllocateConduitAPIMethod' => 'FileConduitAPIMethod',
|
'FileAllocateConduitAPIMethod' => 'FileConduitAPIMethod',
|
||||||
'FileConduitAPIMethod' => 'ConduitAPIMethod',
|
'FileConduitAPIMethod' => 'ConduitAPIMethod',
|
||||||
'FileCreateMailReceiver' => 'PhabricatorMailReceiver',
|
'FileCreateMailReceiver' => 'PhabricatorMailReceiver',
|
||||||
|
'FileDeletionWorker' => 'PhabricatorWorker',
|
||||||
'FileDownloadConduitAPIMethod' => 'FileConduitAPIMethod',
|
'FileDownloadConduitAPIMethod' => 'FileConduitAPIMethod',
|
||||||
'FileInfoConduitAPIMethod' => 'FileConduitAPIMethod',
|
'FileInfoConduitAPIMethod' => 'FileConduitAPIMethod',
|
||||||
'FileMailReceiver' => 'PhabricatorObjectMailReceiver',
|
'FileMailReceiver' => 'PhabricatorObjectMailReceiver',
|
||||||
|
|
|
@ -143,6 +143,7 @@ final class PhabricatorFileDataController extends PhabricatorFileController {
|
||||||
$file = id(new PhabricatorFileQuery())
|
$file = id(new PhabricatorFileQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withPHIDs(array($this->phid))
|
->withPHIDs(array($this->phid))
|
||||||
|
->withIsDeleted(false)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
|
|
||||||
if (!$file) {
|
if (!$file) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ final class PhabricatorFileDeleteController extends PhabricatorFileController {
|
||||||
$file = id(new PhabricatorFileQuery())
|
$file = id(new PhabricatorFileQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withIDs(array($id))
|
->withIDs(array($id))
|
||||||
|
->withIsDeleted(false)
|
||||||
->requireCapabilities(
|
->requireCapabilities(
|
||||||
array(
|
array(
|
||||||
PhabricatorPolicyCapability::CAN_VIEW,
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
@ -25,8 +26,15 @@ final class PhabricatorFileDeleteController extends PhabricatorFileController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
$engine = new PhabricatorDestructionEngine();
|
// Mark the file for deletion, save it, and schedule a worker to
|
||||||
$engine->destroyObject($file);
|
// sweep by later and pick it up.
|
||||||
|
$file->setIsDeleted(true)->save();
|
||||||
|
|
||||||
|
PhabricatorWorker::scheduleTask(
|
||||||
|
'FileDeletionWorker',
|
||||||
|
array('objectPHID' => $file->getPHID()),
|
||||||
|
array('priority' => PhabricatorWorker::PRIORITY_BULK));
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())->setURI('/file/');
|
return id(new AphrontRedirectResponse())->setURI('/file/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
|
||||||
$file = id(new PhabricatorFileQuery())
|
$file = id(new PhabricatorFileQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withPHIDs(array($phid))
|
->withPHIDs(array($phid))
|
||||||
|
->withIsDeleted(false)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
|
|
||||||
if (!$file) {
|
if (!$file) {
|
||||||
|
@ -25,6 +26,7 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
|
||||||
$file = id(new PhabricatorFileQuery())
|
$file = id(new PhabricatorFileQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withIDs(array($id))
|
->withIDs(array($id))
|
||||||
|
->withIsDeleted(false)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if (!$file) {
|
if (!$file) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
|
|
|
@ -36,7 +36,9 @@ final class PhabricatorFileEditEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function newObjectQuery() {
|
protected function newObjectQuery() {
|
||||||
return new PhabricatorFileQuery();
|
$query = new PhabricatorFileQuery();
|
||||||
|
$query->withIsDeleted(false);
|
||||||
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getObjectCreateTitleText($object) {
|
protected function getObjectCreateTitleText($object) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ final class PhabricatorFileQuery
|
||||||
private $maxLength;
|
private $maxLength;
|
||||||
private $names;
|
private $names;
|
||||||
private $isPartial;
|
private $isPartial;
|
||||||
|
private $isDeleted;
|
||||||
private $needTransforms;
|
private $needTransforms;
|
||||||
private $builtinKeys;
|
private $builtinKeys;
|
||||||
|
|
||||||
|
@ -119,6 +120,11 @@ final class PhabricatorFileQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withIsDeleted($deleted) {
|
||||||
|
$this->isDeleted = $deleted;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function withNameNgrams($ngrams) {
|
public function withNameNgrams($ngrams) {
|
||||||
return $this->withNgramsConstraint(
|
return $this->withNgramsConstraint(
|
||||||
id(new PhabricatorFileNameNgrams()),
|
id(new PhabricatorFileNameNgrams()),
|
||||||
|
@ -396,6 +402,13 @@ final class PhabricatorFileQuery
|
||||||
(int)$this->isPartial);
|
(int)$this->isPartial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->isDeleted !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'isDeleted = %d',
|
||||||
|
(int)$this->isDeleted);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->builtinKeys !== null) {
|
if ($this->builtinKeys !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
|
|
|
@ -16,7 +16,9 @@ final class PhabricatorFileSearchEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
public function newQuery() {
|
public function newQuery() {
|
||||||
return new PhabricatorFileQuery();
|
$query = new PhabricatorFileQuery();
|
||||||
|
$query->withIsDeleted(false);
|
||||||
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildCustomSearchFields() {
|
protected function buildCustomSearchFields() {
|
||||||
|
|
|
@ -59,6 +59,7 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
||||||
protected $isExplicitUpload = 1;
|
protected $isExplicitUpload = 1;
|
||||||
protected $viewPolicy = PhabricatorPolicies::POLICY_USER;
|
protected $viewPolicy = PhabricatorPolicies::POLICY_USER;
|
||||||
protected $isPartial = 0;
|
protected $isPartial = 0;
|
||||||
|
protected $isDeleted = 0;
|
||||||
|
|
||||||
private $objects = self::ATTACHABLE;
|
private $objects = self::ATTACHABLE;
|
||||||
private $objectPHIDs = self::ATTACHABLE;
|
private $objectPHIDs = self::ATTACHABLE;
|
||||||
|
@ -103,6 +104,7 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
||||||
'mailKey' => 'bytes20',
|
'mailKey' => 'bytes20',
|
||||||
'isPartial' => 'bool',
|
'isPartial' => 'bool',
|
||||||
'builtinKey' => 'text64?',
|
'builtinKey' => 'text64?',
|
||||||
|
'isDeleted' => 'bool',
|
||||||
),
|
),
|
||||||
self::CONFIG_KEY_SCHEMA => array(
|
self::CONFIG_KEY_SCHEMA => array(
|
||||||
'key_phid' => null,
|
'key_phid' => null,
|
||||||
|
|
31
src/applications/files/worker/FileDeletionWorker.php
Normal file
31
src/applications/files/worker/FileDeletionWorker.php
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class FileDeletionWorker extends PhabricatorWorker {
|
||||||
|
|
||||||
|
private function loadFile() {
|
||||||
|
$phid = idx($this->getTaskData(), 'objectPHID');
|
||||||
|
if (!$phid) {
|
||||||
|
throw new PhabricatorWorkerPermanentFailureException(
|
||||||
|
pht('No "%s" in task data.', 'objectPHID'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = id(new PhabricatorFileQuery())
|
||||||
|
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||||
|
->withPHIDs(array($phid))
|
||||||
|
->executeOne();
|
||||||
|
|
||||||
|
if (!$file) {
|
||||||
|
throw new PhabricatorWorkerPermanentFailureException(
|
||||||
|
pht('File "%s" does not exist.', $phid));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function doWork() {
|
||||||
|
$file = $this->loadFile();
|
||||||
|
$engine = new PhabricatorDestructionEngine();
|
||||||
|
$engine->destroyObject($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue