@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.

When updating revisions in response to commits, reuse previously generated diffs

Summary:
Fixes T10968. In rare situations, we can generate a diff, then hit an error which causes this update to fail.

When it does, we tend to get stuck in a loop creating diffs, which can fill the database up with garbage. We saw this once in the Phacility cluster, and one instance hit it, too.

Instead: when we create a diff, keep track of which commit we generated it from. The next time through, reuse it if we already built it.

Test Plan:
- Used `bin/differential attach-commit <commit> <revision>` to hit this code.
- Simulated a filesystem write failure, saw the diff get reused.
- Also did a normal update, which worked properly.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10968

Differential Revision: https://secure.phabricator.com/D17164

+55 -3
+2
resources/sql/autopatches/20170109.diff.01.commit.sql
··· 1 + ALTER TABLE {$NAMESPACE}_differential.differential_diff 2 + ADD commitPHID VARBINARY(64);
+14
src/applications/differential/engine/DifferentialDiffExtractionEngine.php
··· 26 26 public function newDiffFromCommit(PhabricatorRepositoryCommit $commit) { 27 27 $viewer = $this->getViewer(); 28 28 29 + // If we already have an unattached diff for this commit, just reuse it. 30 + // This stops us from repeatedly generating diffs if something goes wrong 31 + // later in the process. See T10968 for context. 32 + $existing_diffs = id(new DifferentialDiffQuery()) 33 + ->setViewer($viewer) 34 + ->withCommitPHIDs(array($commit->getPHID())) 35 + ->withHasRevision(false) 36 + ->needChangesets(true) 37 + ->execute(); 38 + if ($existing_diffs) { 39 + return head($existing_diffs); 40 + } 41 + 29 42 $repository = $commit->getRepository(); 30 43 $identifier = $commit->getCommitIdentifier(); 31 44 $monogram = $commit->getMonogram(); ··· 73 86 74 87 $diff = DifferentialDiff::newFromRawChanges($viewer, $changes) 75 88 ->setRepositoryPHID($repository->getPHID()) 89 + ->setCommitPHID($commit->getPHID()) 76 90 ->setCreationMethod('commit') 77 91 ->setSourceControlSystem($repository->getVersionControlSystem()) 78 92 ->setLintStatus(DifferentialLintStatus::LINT_AUTO_SKIP)
+34 -3
src/applications/differential/query/DifferentialDiffQuery.php
··· 6 6 private $ids; 7 7 private $phids; 8 8 private $revisionIDs; 9 + private $commitPHIDs; 10 + private $hasRevision; 9 11 10 12 private $needChangesets = false; 11 13 private $needProperties; ··· 22 24 23 25 public function withRevisionIDs(array $revision_ids) { 24 26 $this->revisionIDs = $revision_ids; 27 + return $this; 28 + } 29 + 30 + public function withCommitPHIDs(array $phids) { 31 + $this->commitPHIDs = $phids; 32 + return $this; 33 + } 34 + 35 + public function withHasRevision($has_revision) { 36 + $this->hasRevision = $has_revision; 25 37 return $this; 26 38 } 27 39 ··· 108 120 protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 109 121 $where = parent::buildWhereClauseParts($conn); 110 122 111 - if ($this->ids) { 123 + if ($this->ids !== null) { 112 124 $where[] = qsprintf( 113 125 $conn, 114 126 'id IN (%Ld)', 115 127 $this->ids); 116 128 } 117 129 118 - if ($this->phids) { 130 + if ($this->phids !== null) { 119 131 $where[] = qsprintf( 120 132 $conn, 121 133 'phid IN (%Ls)', 122 134 $this->phids); 123 135 } 124 136 125 - if ($this->revisionIDs) { 137 + if ($this->revisionIDs !== null) { 126 138 $where[] = qsprintf( 127 139 $conn, 128 140 'revisionID IN (%Ld)', 129 141 $this->revisionIDs); 142 + } 143 + 144 + if ($this->commitPHIDs !== null) { 145 + $where[] = qsprintf( 146 + $conn, 147 + 'commitPHID IN (%Ls)', 148 + $this->commitPHIDs); 149 + } 150 + 151 + if ($this->hasRevision !== null) { 152 + if ($this->hasRevision) { 153 + $where[] = qsprintf( 154 + $conn, 155 + 'revisionID IS NOT NULL'); 156 + } else { 157 + $where[] = qsprintf( 158 + $conn, 159 + 'revisionID IS NULL'); 160 + } 130 161 } 131 162 132 163 return $where;
+5
src/applications/differential/storage/DifferentialDiff.php
··· 13 13 protected $revisionID; 14 14 protected $authorPHID; 15 15 protected $repositoryPHID; 16 + protected $commitPHID; 16 17 17 18 protected $sourceMachine; 18 19 protected $sourcePath; ··· 62 63 'branch' => 'text255?', 63 64 'bookmark' => 'text255?', 64 65 'repositoryUUID' => 'text64?', 66 + 'commitPHID' => 'phid?', 65 67 66 68 // T6203/NULLABILITY 67 69 // These should be non-null; all diffs should have a creation method ··· 72 74 self::CONFIG_KEY_SCHEMA => array( 73 75 'revisionID' => array( 74 76 'columns' => array('revisionID'), 77 + ), 78 + 'key_commit' => array( 79 + 'columns' => array('commitPHID'), 75 80 ), 76 81 ), 77 82 ) + parent::getConfiguration();