mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-02 18:08:26 +01:00
Move the "container updated" message for Buildables that build Diffs outside of the transaction
Summary: Ref T13216. See PHI970. Ref T13054. See some discussion in T13216. When a Harbormaster Buildable object is first created for a Diff, it has no `containerPHID` since the revision has not yet been created. We later (after creating a revision) send the Buildable a message telling it that we've added a container and it should re-link the container object. Currently, we send this message in `applyExternalEffects()`, which runs inside the Differential transaction. If Harbormaster races quickly enough, it can read the `Diff` object before the transaction commits, and not see the container update. Add a `didCommitTransaction()` callback after the transactions commit, then move the message code there instead. Test Plan: - See T13216 for substantial evidence that this change is on the right track. - Before change: added `sleep(15)`, reproduced the issue reliably. - After change: unable to reproduce issue even with `sleep(15)` (the `containerPHID` always populates correctly). Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13216, T13054 Differential Revision: https://secure.phabricator.com/D19807
This commit is contained in:
parent
44c32839a6
commit
b2e91d2205
5 changed files with 47 additions and 12 deletions
|
@ -57,6 +57,12 @@ final class DifferentialRevisionUpdateTransaction
|
||||||
// Harbormaster. See discussion in T8650.
|
// Harbormaster. See discussion in T8650.
|
||||||
$diff->setRevisionID($object->getID());
|
$diff->setRevisionID($object->getID());
|
||||||
$diff->save();
|
$diff->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function didCommitTransaction($object, $value) {
|
||||||
|
$editor = $this->getEditor();
|
||||||
|
$diff = $editor->requireDiff($value);
|
||||||
|
$omnipotent = PhabricatorUser::getOmnipotentUser();
|
||||||
|
|
||||||
// If there are any outstanding buildables for this diff, tell
|
// If there are any outstanding buildables for this diff, tell
|
||||||
// Harbormaster that their containers need to be updated. This is
|
// Harbormaster that their containers need to be updated. This is
|
||||||
|
@ -64,7 +70,7 @@ final class DifferentialRevisionUpdateTransaction
|
||||||
// and unit results.
|
// and unit results.
|
||||||
|
|
||||||
$buildables = id(new HarbormasterBuildableQuery())
|
$buildables = id(new HarbormasterBuildableQuery())
|
||||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
->setViewer($omnipotent)
|
||||||
->withManualBuildables(false)
|
->withManualBuildables(false)
|
||||||
->withBuildablePHIDs(array($diff->getPHID()))
|
->withBuildablePHIDs(array($diff->getPHID()))
|
||||||
->execute();
|
->execute();
|
||||||
|
|
|
@ -869,6 +869,24 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
return $xactions;
|
return $xactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final protected function didCommitTransactions(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
array $xactions) {
|
||||||
|
|
||||||
|
foreach ($xactions as $xaction) {
|
||||||
|
$type = $xaction->getTransactionType();
|
||||||
|
|
||||||
|
$xtype = $this->getModularTransactionType($type);
|
||||||
|
if (!$xtype) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$xtype = clone $xtype;
|
||||||
|
$xtype->setStorage($xaction);
|
||||||
|
$xtype->didCommitTransaction($object, $xaction->getNewValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function setContentSource(PhabricatorContentSource $content_source) {
|
public function setContentSource(PhabricatorContentSource $content_source) {
|
||||||
$this->contentSource = $content_source;
|
$this->contentSource = $content_source;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -1106,6 +1124,9 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
$object->saveTransaction();
|
$object->saveTransaction();
|
||||||
$transaction_open = false;
|
$transaction_open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->didCommitTransactions($object, $xactions);
|
||||||
|
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
if ($read_locking) {
|
if ($read_locking) {
|
||||||
$object->endReadLocking();
|
$object->endReadLocking();
|
||||||
|
|
|
@ -35,6 +35,10 @@ abstract class PhabricatorModularTransactionType
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function didCommitTransaction($object, $value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
public function getTransactionHasEffect($object, $old, $new) {
|
public function getTransactionHasEffect($object, $old, $new) {
|
||||||
return ($old !== $new);
|
return ($old !== $new);
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,26 +103,26 @@ abstract class PhabricatorWorkerTaskQuery
|
||||||
return $this->formatWhereClause($conn, $where);
|
return $this->formatWhereClause($conn, $where);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildOrderClause(AphrontDatabaseConnection $conn_r) {
|
protected function buildOrderClause(AphrontDatabaseConnection $conn) {
|
||||||
// NOTE: The garbage collector executes this query with a date constraint,
|
// NOTE: The garbage collector executes this query with a date constraint,
|
||||||
// and the query is inefficient if we don't use the same key for ordering.
|
// and the query is inefficient if we don't use the same key for ordering.
|
||||||
// See T9808 for discussion.
|
// See T9808 for discussion.
|
||||||
|
|
||||||
if ($this->dateCreatedBefore) {
|
if ($this->dateCreatedBefore) {
|
||||||
return qsprintf($conn_r, 'ORDER BY dateCreated DESC, id DESC');
|
return qsprintf($conn, 'ORDER BY dateCreated DESC, id DESC');
|
||||||
} else if ($this->dateModifiedSince) {
|
} else if ($this->dateModifiedSince) {
|
||||||
return qsprintf($conn_r, 'ORDER BY dateModified DESC, id DESC');
|
return qsprintf($conn, 'ORDER BY dateModified DESC, id DESC');
|
||||||
} else {
|
} else {
|
||||||
return qsprintf($conn_r, 'ORDER BY id DESC');
|
return qsprintf($conn, 'ORDER BY id DESC');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildLimitClause(AphrontDatabaseConnection $conn_r) {
|
protected function buildLimitClause(AphrontDatabaseConnection $conn) {
|
||||||
$clause = '';
|
|
||||||
if ($this->limit) {
|
if ($this->limit) {
|
||||||
$clause = qsprintf($conn_r, 'LIMIT %d', $this->limit);
|
return qsprintf($conn, 'LIMIT %d', $this->limit);
|
||||||
|
} else {
|
||||||
|
return qsprintf($conn, '');
|
||||||
}
|
}
|
||||||
return $clause;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,19 +145,23 @@ final class PhabricatorWorkerTriggerQuery
|
||||||
return $triggers;
|
return $triggers;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildJoinClause(AphrontDatabaseConnection $conn_r) {
|
protected function buildJoinClause(AphrontDatabaseConnection $conn) {
|
||||||
$joins = array();
|
$joins = array();
|
||||||
|
|
||||||
if (($this->nextEpochMin !== null) ||
|
if (($this->nextEpochMin !== null) ||
|
||||||
($this->nextEpochMax !== null) ||
|
($this->nextEpochMax !== null) ||
|
||||||
($this->order == self::ORDER_EXECUTION)) {
|
($this->order == self::ORDER_EXECUTION)) {
|
||||||
$joins[] = qsprintf(
|
$joins[] = qsprintf(
|
||||||
$conn_r,
|
$conn,
|
||||||
'JOIN %T e ON e.triggerID = t.id',
|
'JOIN %T e ON e.triggerID = t.id',
|
||||||
id(new PhabricatorWorkerTriggerEvent())->getTableName());
|
id(new PhabricatorWorkerTriggerEvent())->getTableName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return implode(' ', $joins);
|
if ($joins) {
|
||||||
|
return qsprintf($conn, '%LJ', $joins);
|
||||||
|
} else {
|
||||||
|
return qsprintf($conn, '');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
|
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue