Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14873198
D19779.id47265.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
13 KB
Referenced Files
None
Subscribers
None
D19779.id47265.diff
View Options
diff --git a/resources/sql/autopatches/20181106.repo.01.sync.sql b/resources/sql/autopatches/20181106.repo.01.sync.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20181106.repo.01.sync.sql
@@ -0,0 +1,14 @@
+CREATE TABLE {$NAMESPACE}_repository.repository_syncevent (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ repositoryPHID VARBINARY(64) NOT NULL,
+ epoch INT UNSIGNED NOT NULL,
+ devicePHID VARBINARY(64) NOT NULL,
+ fromDevicePHID VARBINARY(64) NOT NULL,
+ deviceVersion INT UNSIGNED,
+ fromDeviceVersion INT UNSIGNED,
+ resultType VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
+ resultCode INT UNSIGNED NOT NULL,
+ syncWait BIGINT UNSIGNED NOT NULL,
+ properties LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -4163,6 +4163,9 @@
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositorySvnCommitMessageParserWorker.php',
'PhabricatorRepositorySymbol' => 'applications/repository/storage/PhabricatorRepositorySymbol.php',
+ 'PhabricatorRepositorySyncEvent' => 'applications/repository/storage/PhabricatorRepositorySyncEvent.php',
+ 'PhabricatorRepositorySyncEventPHIDType' => 'applications/repository/phid/PhabricatorRepositorySyncEventPHIDType.php',
+ 'PhabricatorRepositorySyncEventQuery' => 'applications/repository/query/PhabricatorRepositorySyncEventQuery.php',
'PhabricatorRepositoryTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryTestCase.php',
'PhabricatorRepositoryTransaction' => 'applications/repository/storage/PhabricatorRepositoryTransaction.php',
'PhabricatorRepositoryTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryTransactionQuery.php',
@@ -10111,6 +10114,12 @@
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO',
+ 'PhabricatorRepositorySyncEvent' => array(
+ 'PhabricatorRepositoryDAO',
+ 'PhabricatorPolicyInterface',
+ ),
+ 'PhabricatorRepositorySyncEventPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorRepositorySyncEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorRepositoryTestCase' => 'PhabricatorTestCase',
'PhabricatorRepositoryTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorRepositoryTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
diff --git a/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php b/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php
--- a/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php
+++ b/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php
@@ -206,7 +206,10 @@
}
}
- $this->synchronizeWorkingCopyFromDevices($fetchable);
+ $this->synchronizeWorkingCopyFromDevices(
+ $fetchable,
+ $this_version,
+ $max_version);
} else {
$this->synchronizeWorkingCopyFromRemote();
}
@@ -653,7 +656,11 @@
/**
* @task internal
*/
- private function synchronizeWorkingCopyFromDevices(array $device_phids) {
+ private function synchronizeWorkingCopyFromDevices(
+ array $device_phids,
+ $local_version,
+ $remote_version) {
+
$repository = $this->getRepository();
$service = $repository->loadAlmanacService();
@@ -694,7 +701,10 @@
$caught = null;
foreach ($fetchable as $binding) {
try {
- $this->synchronizeWorkingCopyFromBinding($binding);
+ $this->synchronizeWorkingCopyFromBinding(
+ $binding,
+ $local_version,
+ $remote_version);
$caught = null;
break;
} catch (Exception $ex) {
@@ -711,14 +721,17 @@
/**
* @task internal
*/
- private function synchronizeWorkingCopyFromBinding($binding) {
+ private function synchronizeWorkingCopyFromBinding(
+ AlmanacBinding $binding,
+ $local_version,
+ $remote_version) {
+
$repository = $this->getRepository();
$device = AlmanacKeys::getLiveDevice();
$this->logLine(
pht(
- 'Synchronizing this device ("%s") from cluster leader ("%s") before '.
- 'read.',
+ 'Synchronizing this device ("%s") from cluster leader ("%s").',
$device->getName(),
$binding->getDevice()->getName()));
@@ -746,17 +759,60 @@
$future->setCWD($local_path);
+ $log = PhabricatorRepositorySyncEvent::initializeNewEvent()
+ ->setRepositoryPHID($repository->getPHID())
+ ->setEpoch(PhabricatorTime::getNow())
+ ->setDevicePHID($device->getPHID())
+ ->setFromDevicePHID($binding->getDevice()->getPHID())
+ ->setDeviceVersion($local_version)
+ ->setFromDeviceVersion($remote_version);
+
+ $sync_start = microtime(true);
+
try {
$future->resolvex();
} catch (Exception $ex) {
+ $sync_end = microtime(true);
+ $log->setSyncWait((int)(1000000 * ($sync_end - $sync_start)));
+
+ if ($ex instanceof CommandException) {
+ if ($future->getWasKilledByTimeout()) {
+ $result_type = PhabricatorRepositorySyncEvent::RESULT_TIMEOUT;
+ } else {
+ $result_type = PhabricatorRepositorySyncEvent::RESULT_ERROR;
+ }
+
+ $log
+ ->setResultCode($ex->getError())
+ ->setResultType($result_type)
+ ->setProperty('stdout', $ex->getStdout())
+ ->setProperty('stderr', $ex->getStderr());
+ } else {
+ $log
+ ->setResultCode(1)
+ ->setResultType(PhabricatorRepositorySyncEvent::RESULT_EXCEPTION)
+ ->setProperty('message', $ex->getMessage());
+ }
+
+ $log->save();
+
$this->logLine(
pht(
'Synchronization of "%s" from leader "%s" failed: %s',
$device->getName(),
$binding->getDevice()->getName(),
$ex->getMessage()));
+
throw $ex;
}
+
+ $sync_end = microtime(true);
+
+ $log
+ ->setSyncWait((int)(1000000 * ($sync_end - $sync_start)))
+ ->setResultCode(0)
+ ->setResultType(PhabricatorRepositorySyncEvent::RESULT_SYNC)
+ ->save();
}
diff --git a/src/applications/repository/phid/PhabricatorRepositorySyncEventPHIDType.php b/src/applications/repository/phid/PhabricatorRepositorySyncEventPHIDType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/phid/PhabricatorRepositorySyncEventPHIDType.php
@@ -0,0 +1,39 @@
+<?php
+
+final class PhabricatorRepositorySyncEventPHIDType extends PhabricatorPHIDType {
+
+ const TYPECONST = 'SYNE';
+
+ public function getTypeName() {
+ return pht('Sync Event');
+ }
+
+ public function newObject() {
+ return new PhabricatorRepositorySyncEvent();
+ }
+
+ public function getPHIDTypeApplicationClass() {
+ return 'PhabricatorDiffusionApplication';
+ }
+
+ protected function buildQueryForObjects(
+ PhabricatorObjectQuery $query,
+ array $phids) {
+
+ return id(new PhabricatorRepositorySyncEventQuery())
+ ->withPHIDs($phids);
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {
+
+ foreach ($handles as $phid => $handle) {
+ $event = $objects[$phid];
+
+ $handle->setName(pht('Sync Event %d', $event->getID()));
+ }
+ }
+
+}
diff --git a/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php b/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/query/PhabricatorRepositorySyncEventQuery.php
@@ -0,0 +1,115 @@
+<?php
+
+final class PhabricatorRepositorySyncEventQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+ private $repositoryPHIDs;
+ private $epochMin;
+ private $epochMax;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withRepositoryPHIDs(array $repository_phids) {
+ $this->repositoryPHIDs = $repository_phids;
+ return $this;
+ }
+
+ public function withEpochBetween($min, $max) {
+ $this->epochMin = $min;
+ $this->epochMax = $max;
+ return $this;
+ }
+
+ public function newResultObject() {
+ return new PhabricatorRepositoryPullEvent();
+ }
+
+ protected function loadPage() {
+ return $this->loadStandardPage($this->newResultObject());
+ }
+
+ protected function willFilterPage(array $events) {
+ $repository_phids = mpull($events, 'getRepositoryPHID');
+ $repository_phids = array_filter($repository_phids);
+
+ if ($repository_phids) {
+ $repositories = id(new PhabricatorRepositoryQuery())
+ ->setViewer($this->getViewer())
+ ->withPHIDs($repository_phids)
+ ->execute();
+ $repositories = mpull($repositories, null, 'getPHID');
+ } else {
+ $repositories = array();
+ }
+
+ foreach ($events as $key => $event) {
+ $phid = $event->getRepositoryPHID();
+
+ if (empty($repositories[$phid])) {
+ unset($events[$key]);
+ $this->didRejectResult($event);
+ continue;
+ }
+
+ $event->attachRepository($repositories[$phid]);
+ }
+
+ return $events;
+ }
+
+ protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
+ $where = parent::buildWhereClauseParts($conn);
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->repositoryPHIDs !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'repositoryPHID IN (%Ls)',
+ $this->repositoryPHIDs);
+ }
+
+ if ($this->epochMin !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'epoch >= %d',
+ $this->epochMin);
+ }
+
+ if ($this->epochMax !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'epoch <= %d',
+ $this->epochMax);
+ }
+
+ return $where;
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorDiffusionApplication';
+ }
+
+}
diff --git a/src/applications/repository/storage/PhabricatorRepositorySyncEvent.php b/src/applications/repository/storage/PhabricatorRepositorySyncEvent.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/storage/PhabricatorRepositorySyncEvent.php
@@ -0,0 +1,99 @@
+<?php
+
+final class PhabricatorRepositorySyncEvent
+ extends PhabricatorRepositoryDAO
+ implements PhabricatorPolicyInterface {
+
+ protected $repositoryPHID;
+ protected $epoch;
+ protected $devicePHID;
+ protected $fromDevicePHID;
+ protected $deviceVersion;
+ protected $fromDeviceVersion;
+ protected $resultType;
+ protected $resultCode;
+ protected $syncWait;
+ protected $properties = array();
+
+ private $repository = self::ATTACHABLE;
+
+ const RESULT_SYNC = 'sync';
+ const RESULT_ERROR = 'error';
+ const RESULT_TIMEOUT = 'timeout';
+ const RESULT_EXCEPTION = 'exception';
+
+ public static function initializeNewEvent() {
+ return new self();
+ }
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => true,
+ self::CONFIG_TIMESTAMPS => false,
+ self::CONFIG_SERIALIZATION => array(
+ 'properties' => self::SERIALIZATION_JSON,
+ ),
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'deviceVersion' => 'uint32?',
+ 'fromDeviceVersion' => 'uint32?',
+ 'resultType' => 'text32',
+ 'resultCode' => 'uint32',
+ 'syncWait' => 'uint64',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_repository' => array(
+ 'columns' => array('repositoryPHID'),
+ ),
+ 'key_epoch' => array(
+ 'columns' => array('epoch'),
+ ),
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function getPHIDType() {
+ return PhabricatorRepositorySyncEventPHIDType::TYPECONST;
+ }
+
+ public function attachRepository(PhabricatorRepository $repository) {
+ $this->repository = $repository;
+ return $this;
+ }
+
+ public function getRepository() {
+ return $this->assertAttached($this->repository);
+ }
+
+ public function setProperty($key, $value) {
+ $this->properites[$key] = $value;
+ return $this;
+ }
+
+ public function getProperty($key, $default = null) {
+ return idx($this->properties, $key, $default);
+ }
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ );
+ }
+
+ public function getPolicy($capability) {
+ return $this->getRepository()->getPolicy($capability);
+ }
+
+ public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+ return $this->getRepository()->hasAutomaticCapability($capability, $viewer);
+ }
+
+ public function describeAutomaticCapability($capability) {
+ return pht(
+ "A repository's sync events are visible to users who can see the ".
+ "repository.");
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 9, 5:01 AM (20 h, 34 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7106029
Default Alt Text
D19779.id47265.diff (13 KB)
Attached To
Mode
D19779: Add an intracluster synchronization log for cluster repositories
Attached
Detach File
Event Timeline
Log In to Comment