1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-02 03:32:42 +01:00

Label transaction groups with a "group ID" so Herald can reconstruct them faithfully

Summary:
Ref T13283. See PHI1202. See D20519. When we apply a group of transactions, label all of them with the same "group ID".

This allows other things, notably Herald, to figure out which transactions applied together in a faithful way rather than by guessing, even though the guess was probably pretty good most of the time.

Also expose this to `transaction.search` in case callers want to do something similar. They get a list of transaction IDs from webhooks already anyway, but some callers use `transaction.search` outside of webhooks and this information may be useful.

Test Plan:
  - Ran Herald Test Console, saw faithful selection of recent transactions.
  - Changed hard limit from 1000 to 1, saw exception. Users should be very hard-pressed to hit this normally (they'd have to add 990-ish custom fields, then edit every field at once, I think) so I'm just fataling rather than processing some subset of the transaction set.
  - Called `transaction.search`, saw group ID information available.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13283

Differential Revision: https://secure.phabricator.com/D20524
This commit is contained in:
epriestley 2019-05-16 12:56:58 -07:00
parent 6bff2cee22
commit 167f06d3eb
4 changed files with 54 additions and 10 deletions

View file

@ -260,24 +260,48 @@ final class HeraldTestConsoleController extends HeraldController {
$query = PhabricatorApplicationTransactionQuery::newQueryForObject( $query = PhabricatorApplicationTransactionQuery::newQueryForObject(
$object); $object);
$xactions = $query $query
->withObjectPHIDs(array($object->getPHID())) ->withObjectPHIDs(array($object->getPHID()))
->setViewer($viewer) ->setViewer($viewer);
->setLimit(100)
->execute(); $xactions = new PhabricatorQueryIterator($query);
$applied = array(); $applied = array();
// Pick the most recent group of transactions. This may not be exactly the $recent_id = null;
// same as what Herald acted on: for example, we may select a single group $hard_limit = 1000;
// of transactions here which were really applied across two or more edits.
// Since this is relatively rare and we show you what we picked, it's okay
// that we just do roughly the right thing.
foreach ($xactions as $xaction) { foreach ($xactions as $xaction) {
if (!$xaction->shouldDisplayGroupWith($applied)) { $group_id = $xaction->getTransactionGroupID();
// If this is the first transaction, save the group ID: we want to
// select all transactions in the same group.
if (!$applied) {
$recent_id = $group_id;
if ($recent_id === null) {
// If the first transaction has no group ID, it is likely an older
// transaction from before the introduction of group IDs. In this
// case, select only the most recent transaction and bail out.
$applied[] = $xaction;
break; break;
} }
}
// If this transaction is from a different transaction group, we've
// found all the transactions applied in the most recent group.
if ($group_id !== $recent_id) {
break;
}
$applied[] = $xaction; $applied[] = $xaction;
if (count($applied) > $hard_limit) {
throw new Exception(
pht(
'This object ("%s") has more than %s transactions in its most '.
'recent transaction group; this is too many.',
$object->getPHID(),
new PhutilNumber($hard_limit)));
}
} }
return $applied; return $applied;

View file

@ -260,6 +260,13 @@ EOREMARKUP
} }
} }
$group_id = $xaction->getTransactionGroupID();
if (!strlen($group_id)) {
$group_id = null;
} else {
$group_id = (string)$group_id;
}
$data[] = array( $data[] = array(
'id' => (int)$xaction->getID(), 'id' => (int)$xaction->getID(),
'phid' => (string)$xaction->getPHID(), 'phid' => (string)$xaction->getPHID(),
@ -268,6 +275,7 @@ EOREMARKUP
'objectPHID' => (string)$xaction->getObjectPHID(), 'objectPHID' => (string)$xaction->getObjectPHID(),
'dateCreated' => (int)$xaction->getDateCreated(), 'dateCreated' => (int)$xaction->getDateCreated(),
'dateModified' => (int)$xaction->getDateModified(), 'dateModified' => (int)$xaction->getDateModified(),
'groupID' => $group_id,
'comments' => $comment_data, 'comments' => $comment_data,
'fields' => $fields, 'fields' => $fields,
); );

View file

@ -1162,6 +1162,8 @@ abstract class PhabricatorApplicationTransactionEditor
throw $ex; throw $ex;
} }
$group_id = Filesystem::readRandomCharacters(32);
foreach ($xactions as $xaction) { foreach ($xactions as $xaction) {
if ($was_locked) { if ($was_locked) {
$is_override = $this->isLockOverrideTransaction($xaction); $is_override = $this->isLockOverrideTransaction($xaction);
@ -1171,6 +1173,8 @@ abstract class PhabricatorApplicationTransactionEditor
} }
$xaction->setObjectPHID($object->getPHID()); $xaction->setObjectPHID($object->getPHID());
$xaction->setTransactionGroupID($group_id);
if ($xaction->getComment()) { if ($xaction->getComment()) {
$xaction->setPHID($xaction->generatePHID()); $xaction->setPHID($xaction->generatePHID());
$comment_editor->applyEdit($xaction, $xaction->getComment()); $comment_editor->applyEdit($xaction, $xaction->getComment());

View file

@ -177,6 +177,14 @@ abstract class PhabricatorApplicationTransaction
return (bool)$this->getMetadataValue('core.lock-override', false); return (bool)$this->getMetadataValue('core.lock-override', false);
} }
public function setTransactionGroupID($group_id) {
return $this->setMetadataValue('core.groupID', $group_id);
}
public function getTransactionGroupID() {
return $this->getMetadataValue('core.groupID', null);
}
public function attachComment( public function attachComment(
PhabricatorApplicationTransactionComment $comment) { PhabricatorApplicationTransactionComment $comment) {
$this->comment = $comment; $this->comment = $comment;