From 8bcbeface1769d36d4cd419b513795c916269818 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 11 Mar 2011 09:34:22 -0800 Subject: [PATCH] Increase parseriness of some parsery things. Summary: None of these are parsnips. Test Plan: Reviewers: CC: --- resources/sql/patches/006.repository.sql | 42 ++++ src/__phutil_library_map__.php | 28 ++- ...AphrontDefaultApplicationConfiguration.php | 4 + .../base/PhabricatorDaemonController.php | 6 +- .../PhabricatorDaemonConsoleController.php | 103 +++++++-- .../daemon/controller/console/__init__.php | 3 + ...ricatorDaemonTimelineConsoleController.php | 70 ++++++ .../daemon/controller/timeline/__init__.php | 18 ++ ...abricatorDaemonTimelineEventController.php | 79 +++++++ .../controller/timelineevent/__init__.php | 20 ++ .../commit/DiffusionCommitController.php | 55 +++++ .../diffusion/controller/commit/__init__.php | 14 ++ .../DiffusionCommitChangeTableView.php | 63 +++++ ...ricatorRepositoryCommitDiscoveryDaemon.php | 51 +++++ .../daemon/commitdiscovery/base/__init__.php | 4 + ...atorRepositoryGitCommitDiscoveryDaemon.php | 54 +---- .../daemon/commitdiscovery/git/__init__.php | 4 +- ...atorRepositorySvnCommitDiscoveryDaemon.php | 77 +++++++ .../daemon/commitdiscovery/svn/__init__.php | 15 ++ .../daemon/commitparser/__init__.php | 12 - .../PhabricatorRepositoryCommitTaskDaemon.php | 72 ++++++ .../repository/daemon/committask/__init__.php | 19 ++ .../PhabricatorRepositoryCommitData.php} | 13 +- .../storage/commitdata/__init__.php | 12 + .../repository/PhabricatorRepository.php | 3 + ...habricatorRepositoryCommitParserWorker.php | 54 +++++ .../repository/worker/base/__init__.php | 16 ++ ...atorRepositoryCommitChangeParserWorker.php | 69 ++++++ .../commitchangeparser/base/__init__.php | 15 ++ ...rRepositoryGitCommitChangeParserWorker.php | 215 ++++++++++++++++++ .../commitchangeparser/git/__init__.php | 17 ++ ...torRepositoryCommitMessageParserWorker.php | 37 +++ .../commitmessageparser/base/__init__.php | 15 ++ ...RepositoryGitCommitMessageParserWorker.php | 45 ++++ .../commitmessageparser/git/__init__.php | 15 ++ ...RepositorySvnCommitMessageParserWorker.php | 44 ++++ .../commitmessageparser/svn/__init__.php | 14 ++ .../iterator/PhabricatorTimelineIterator.php | 7 +- .../cursor/PhabricatorTimelineCursor.php | 11 + .../storage/task/PhabricatorWorkerTask.php | 26 ++- .../daemon/workers/storage/task/__init__.php | 1 + .../PhabricatorTaskmasterDaemon.php | 17 +- 42 files changed, 1359 insertions(+), 100 deletions(-) create mode 100644 resources/sql/patches/006.repository.sql create mode 100644 src/applications/daemon/controller/timeline/PhabricatorDaemonTimelineConsoleController.php create mode 100644 src/applications/daemon/controller/timeline/__init__.php create mode 100644 src/applications/daemon/controller/timelineevent/PhabricatorDaemonTimelineEventController.php create mode 100644 src/applications/daemon/controller/timelineevent/__init__.php create mode 100644 src/applications/diffusion/controller/commit/DiffusionCommitController.php create mode 100644 src/applications/diffusion/controller/commit/__init__.php create mode 100644 src/applications/diffusion/view/commitchangetable/DiffusionCommitChangeTableView.php create mode 100644 src/applications/repository/daemon/commitdiscovery/svn/PhabricatorRepositorySvnCommitDiscoveryDaemon.php create mode 100644 src/applications/repository/daemon/commitdiscovery/svn/__init__.php delete mode 100644 src/applications/repository/daemon/commitparser/__init__.php create mode 100644 src/applications/repository/daemon/committask/PhabricatorRepositoryCommitTaskDaemon.php create mode 100644 src/applications/repository/daemon/committask/__init__.php rename src/applications/repository/{daemon/commitparser/PhabricatorRepositoryCommitParserDaemon.php => storage/commitdata/PhabricatorRepositoryCommitData.php} (67%) create mode 100644 src/applications/repository/storage/commitdata/__init__.php create mode 100644 src/applications/repository/worker/base/PhabricatorRepositoryCommitParserWorker.php create mode 100644 src/applications/repository/worker/base/__init__.php create mode 100644 src/applications/repository/worker/commitchangeparser/base/PhabricatorRepositoryCommitChangeParserWorker.php create mode 100644 src/applications/repository/worker/commitchangeparser/base/__init__.php create mode 100644 src/applications/repository/worker/commitchangeparser/git/PhabricatorRepositoryGitCommitChangeParserWorker.php create mode 100644 src/applications/repository/worker/commitchangeparser/git/__init__.php create mode 100644 src/applications/repository/worker/commitmessageparser/base/PhabricatorRepositoryCommitMessageParserWorker.php create mode 100644 src/applications/repository/worker/commitmessageparser/base/__init__.php create mode 100644 src/applications/repository/worker/commitmessageparser/git/PhabricatorRepositoryGitCommitMessageParserWorker.php create mode 100644 src/applications/repository/worker/commitmessageparser/git/__init__.php create mode 100644 src/applications/repository/worker/commitmessageparser/svn/PhabricatorRepositorySvnCommitMessageParserWorker.php create mode 100644 src/applications/repository/worker/commitmessageparser/svn/__init__.php diff --git a/resources/sql/patches/006.repository.sql b/resources/sql/patches/006.repository.sql new file mode 100644 index 0000000000..569437c2c1 --- /dev/null +++ b/resources/sql/patches/006.repository.sql @@ -0,0 +1,42 @@ +create table phabricator_repository.repository_commitdata ( + id int unsigned not null auto_increment primary key, + commitID int unsigned not null, + authorName varchar(255) not null, + commitMessage longblob not null, + unique key (commitID), + key (authorName) +); + +ALTER TABLE phabricator_worker.worker_task drop priority; +ALTER TABLE phabricator_worker.worker_task drop key leaseOwner; +ALTER TABLE phabricator_worker.worker_task drop key (leaseOwner(16)); + +create table phabricator_repository.repository_path ( + id int unsigned not null auto_increment primary key, + path varchar(512) not null, + unique key (path) +); + +create table phabricator_repository.repository_pathchange ( + repositoryID int unsigned NOT NULL, + pathID int unsigned NOT NULL, + commitID int unsigned NOT NULL, + targetPathID int unsigned, + targetCommitID int unsigned, + changeType int unsigned NOT NULL, + fileType int unsigned NOT NULL, + isDirect bool NOT NULL, + commitSequence int unsigned NOT NULL, + primary key (commitID, pathID), + key (repositoryID, pathID, commitSequence) +); + +create table phabricator_repository.repository_filesystem ( + repositoryID int unsigned not null, + parentID int unsigned not null, + svnCommit int unsigned not null, + pathID int unsigned not null, + existed bool not null, + fileType int unsigned not null, + primary key (repositoryID, parentID, svnCommit, pathID) +); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 65be1069ec..5eef3533c0 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -146,6 +146,8 @@ phutil_register_library_map(array( 'DiffusionBrowseFileController' => 'applications/diffusion/controller/file', 'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/base', 'DiffusionBrowseTableView' => 'applications/diffusion/view/browsetable', + 'DiffusionCommitChangeTableView' => 'applications/diffusion/view/commitchangetable', + 'DiffusionCommitController' => 'applications/diffusion/controller/commit', 'DiffusionController' => 'applications/diffusion/controller/base', 'DiffusionFileContent' => 'applications/diffusion/data/filecontent', 'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/base', @@ -192,6 +194,8 @@ phutil_register_library_map(array( 'PhabricatorDaemon' => 'infrastructure/daemon/base', 'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/console', 'PhabricatorDaemonController' => 'applications/daemon/controller/base', + 'PhabricatorDaemonTimelineConsoleController' => 'applications/daemon/controller/timeline', + 'PhabricatorDaemonTimelineEventController' => 'applications/daemon/controller/timelineevent', 'PhabricatorDirectoryCategory' => 'applications/directory/storage/category', 'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete', 'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit', @@ -274,18 +278,26 @@ phutil_register_library_map(array( 'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/remarkup/markuprule/maniphest', 'PhabricatorRepository' => 'applications/repository/storage/repository', 'PhabricatorRepositoryCommit' => 'applications/repository/storage/commit', + 'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/base', + 'PhabricatorRepositoryCommitData' => 'applications/repository/storage/commitdata', 'PhabricatorRepositoryCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/base', - 'PhabricatorRepositoryCommitParserDaemon' => 'applications/repository/daemon/commitparser', + 'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/base', + 'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/base', + 'PhabricatorRepositoryCommitTaskDaemon' => 'applications/repository/daemon/committask', 'PhabricatorRepositoryController' => 'applications/repository/controller/base', 'PhabricatorRepositoryCreateController' => 'applications/repository/controller/create', 'PhabricatorRepositoryDAO' => 'applications/repository/storage/base', 'PhabricatorRepositoryDaemon' => 'applications/repository/daemon/base', 'PhabricatorRepositoryEditController' => 'applications/repository/controller/edit', + 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/git', 'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/git', + 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/git', 'PhabricatorRepositoryGitHubNotification' => 'applications/repository/storage/githubnotification', 'PhabricatorRepositoryGitHubPostReceiveController' => 'applications/repository/controller/github-post-receive', 'PhabricatorRepositoryGitPullDaemon' => 'applications/repository/daemon/gitpull', 'PhabricatorRepositoryListController' => 'applications/repository/controller/list', + 'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/svn', + 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/svn', 'PhabricatorRepositoryType' => 'applications/repository/constants/repositorytype', 'PhabricatorSearchAbstractDocument' => 'applications/search/index/abstractdocument', 'PhabricatorSearchBaseController' => 'applications/search/controller/base', @@ -449,6 +461,8 @@ phutil_register_library_map(array( 'DiffusionBrowseController' => 'DiffusionController', 'DiffusionBrowseFileController' => 'DiffusionController', 'DiffusionBrowseTableView' => 'AphrontView', + 'DiffusionCommitChangeTableView' => 'AphrontView', + 'DiffusionCommitController' => 'DiffusionController', 'DiffusionController' => 'PhabricatorController', 'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery', 'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery', @@ -483,6 +497,8 @@ phutil_register_library_map(array( 'PhabricatorDaemon' => 'PhutilDaemon', 'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController', 'PhabricatorDaemonController' => 'PhabricatorController', + 'PhabricatorDaemonTimelineConsoleController' => 'PhabricatorDaemonController', + 'PhabricatorDaemonTimelineEventController' => 'PhabricatorDaemonController', 'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO', 'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController', @@ -555,18 +571,26 @@ phutil_register_library_map(array( 'PhabricatorRemarkupRuleManiphest' => 'PhutilRemarkupRule', 'PhabricatorRepository' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCommit' => 'PhabricatorRepositoryDAO', + 'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker', + 'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCommitDiscoveryDaemon' => 'PhabricatorRepositoryDaemon', - 'PhabricatorRepositoryCommitParserDaemon' => 'PhabricatorRepositoryDaemon', + 'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker', + 'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker', + 'PhabricatorRepositoryCommitTaskDaemon' => 'PhabricatorRepositoryDaemon', 'PhabricatorRepositoryController' => 'PhabricatorController', 'PhabricatorRepositoryCreateController' => 'PhabricatorController', 'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO', 'PhabricatorRepositoryDaemon' => 'PhabricatorDaemon', 'PhabricatorRepositoryEditController' => 'PhabricatorController', + 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon', + 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositoryGitHubNotification' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryGitHubPostReceiveController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryGitPullDaemon' => 'PhabricatorRepositoryDaemon', 'PhabricatorRepositoryListController' => 'PhabricatorController', + 'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon', + 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorSearchBaseController' => 'PhabricatorController', 'PhabricatorSearchController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchDAO' => 'PhabricatorLiskDAO', diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php index 43c13010e4..aa07c7cbe1 100644 --- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php +++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php @@ -183,6 +183,8 @@ class AphrontDefaultApplicationConfiguration => 'PhabricatorProjectAffiliationEditController', ), + '/r(?P[A-Z]+)(?P[a-z0-9]+)$' + => 'DiffusionCommitController', '/diffusion/' => array( '$' => 'DiffusionHomeController', '(?P[A-Z]+)' => array( @@ -201,6 +203,8 @@ class AphrontDefaultApplicationConfiguration ), '/daemon/' => array( + 'timeline/$' => 'PhabricatorDaemonTimelineConsoleController', + 'timeline/(?P\d+)/$' => 'PhabricatorDaemonTimelineEventController', '$' => 'PhabricatorDaemonConsoleController', ), diff --git a/src/applications/daemon/controller/base/PhabricatorDaemonController.php b/src/applications/daemon/controller/base/PhabricatorDaemonController.php index 9892426fd0..c0ab524416 100644 --- a/src/applications/daemon/controller/base/PhabricatorDaemonController.php +++ b/src/applications/daemon/controller/base/PhabricatorDaemonController.php @@ -22,7 +22,7 @@ abstract class PhabricatorDaemonController extends PhabricatorController { $page = $this->buildStandardPageView(); $page->setApplicationName('Daemon Console'); - $page->setBaseURI('/'); + $page->setBaseURI('/daemon/'); $page->setTitle(idx($data, 'title')); $page->setTabs( array( @@ -30,6 +30,10 @@ abstract class PhabricatorDaemonController extends PhabricatorController { 'href' => '/daemon/', 'name' => 'Console', ), + 'timeline' => array( + 'href' => '/daemon/timeline/', + 'name' => 'Timeline', + ), ), idx($data, 'tab')); $page->setGlyph("\xE2\x98\xAF"); diff --git a/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php b/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php index 9e40ae17b2..2a3a797ac7 100644 --- a/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php +++ b/src/applications/daemon/controller/console/PhabricatorDaemonConsoleController.php @@ -19,18 +19,8 @@ class PhabricatorDaemonConsoleController extends PhabricatorDaemonController { public function processRequest() { - $request = $this->getRequest(); - - if ($request->getStr('new')) { - $task = new PhabricatorWorkerTask(); - $task->setTaskClass('PhabricatorGoodForNothingWorker'); - $task->setPriority(4); - $task->setFailureCount(0); - $task->save(); - } - - $tasks = id(new PhabricatorWorkerTask()) - ->loadAll(); + $tasks = id(new PhabricatorWorkerTask())->loadAllWhere( + 'leaseOwner IS NOT NULL'); $rows = array(); foreach ($tasks as $task) { @@ -38,29 +28,100 @@ class PhabricatorDaemonConsoleController extends PhabricatorDaemonController { $task->getID(), $task->getTaskClass(), $task->getLeaseOwner(), - $task->getLeaseExpires(), - $task->getPriority(), + $task->getLeaseExpires() - time(), $task->getFailureCount(), ); } - $table = new AphrontTableView($rows); - $table->setHeaders( + $leased_table = new AphrontTableView($rows); + $leased_table->setHeaders( array( 'ID', 'Class', 'Owner', 'Expries', - 'Priority', + 'Failures', + )); + $leased_table->setColumnClasses( + array( + 'n', + 'wide', + '', + '', + 'n', + )); + $leased_table->setNoDataString('No tasks are leased by workers.'); + + $leased_panel = new AphrontPanelView(); + $leased_panel->setHeader('Leased Tasks'); + $leased_panel->appendChild($leased_table); + + $task_table = new PhabricatorWorkerTask(); + $queued = queryfx_all( + $task_table->establishConnection('r'), + 'SELECT taskClass, count(*) N FROM %T GROUP BY taskClass + ORDER BY N DESC', + $task_table->getTableName()); + + $rows = array(); + foreach ($queued as $row) { + $rows[] = array( + phutil_escape_html($row['taskClass']), + number_format($row['N']), + ); + } + + $queued_table = new AphrontTableView($rows); + $queued_table->setHeaders( + array( + 'Class', 'Count', )); + $queued_table->setColumnClasses( + array( + 'wide', + 'n', + )); + $queued_table->setNoDataString('Task queue is empty.'); - $panel = new AphrontPanelView(); - $panel->setHeader('Tasks'); - $panel->appendChild($table); + $queued_panel = new AphrontPanelView(); + $queued_panel->setHeader('Queued Tasks'); + $queued_panel->appendChild($queued_table); + + $cursors = id(new PhabricatorTimelineCursor()) + ->loadAll(); + + $rows = array(); + foreach ($cursors as $cursor) { + $rows[] = array( + phutil_escape_html($cursor->getName()), + number_format($cursor->getPosition()), + ); + } + + $cursor_table = new AphrontTableView($rows); + $cursor_table->setHeaders( + array( + 'Name', + 'Position', + )); + $cursor_table->setColumnClasses( + array( + 'wide', + 'n', + )); + $cursor_table->setNoDataString('No timeline cursors exist.'); + + $cursor_panel = new AphrontPanelView(); + $cursor_panel->setHeader('Timeline Cursors'); + $cursor_panel->appendChild($cursor_table); return $this->buildStandardPageResponse( - $panel, + array( + $leased_panel, + $queued_panel, + $cursor_panel, + ), array( 'title' => 'Console', 'tab' => 'console', diff --git a/src/applications/daemon/controller/console/__init__.php b/src/applications/daemon/controller/console/__init__.php index 28cdb0bf7a..c07c4dd43a 100644 --- a/src/applications/daemon/controller/console/__init__.php +++ b/src/applications/daemon/controller/console/__init__.php @@ -7,10 +7,13 @@ phutil_require_module('phabricator', 'applications/daemon/controller/base'); +phutil_require_module('phabricator', 'infrastructure/daemon/timeline/storage/cursor'); phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/task'); +phutil_require_module('phabricator', 'storage/queryfx'); phutil_require_module('phabricator', 'view/control/table'); phutil_require_module('phabricator', 'view/layout/panel'); +phutil_require_module('phutil', 'markup'); phutil_require_module('phutil', 'utils'); diff --git a/src/applications/daemon/controller/timeline/PhabricatorDaemonTimelineConsoleController.php b/src/applications/daemon/controller/timeline/PhabricatorDaemonTimelineConsoleController.php new file mode 100644 index 0000000000..36fed14a97 --- /dev/null +++ b/src/applications/daemon/controller/timeline/PhabricatorDaemonTimelineConsoleController.php @@ -0,0 +1,70 @@ +establishConnection('r'), + 'SELECT id, type FROM %T ORDER BY id DESC LIMIT 100', + $timeline_table->getTableName()); + + $rows = array(); + foreach ($events as $event) { + $rows[] = array( + phutil_render_tag( + 'a', + array( + 'href' => '/daemon/timeline/'.$event['id'].'/', + ), + $event['id']), + phutil_escape_html($event['type']), + ); + } + + $event_table = new AphrontTableView($rows); + $event_table->setHeaders( + array( + 'ID', + 'Type', + )); + $event_table->setColumnClasses( + array( + null, + 'wide', + )); + + $event_panel = new AphrontPanelView(); + $event_panel->setHeader('Timeline Events'); + $event_panel->appendChild($event_table); + + return $this->buildStandardPageResponse( + array( + $event_panel, + ), + array( + 'title' => 'Timeline', + 'tab' => 'timeline', + )); + } + +} diff --git a/src/applications/daemon/controller/timeline/__init__.php b/src/applications/daemon/controller/timeline/__init__.php new file mode 100644 index 0000000000..933eef2d80 --- /dev/null +++ b/src/applications/daemon/controller/timeline/__init__.php @@ -0,0 +1,18 @@ +id = $data['id']; + } + + public function processRequest() { + $event = id(new PhabricatorTimelineEvent('NULL'))->load($this->id); + if (!$event) { + return new Aphront404Response(); + } + + $request = $this->getRequest(); + $user = $request->getUser(); + + $data = id(new PhabricatorTimelineEventData())->loadOneWhere( + 'eventID = %d', + $event->getID()); + + if ($data) { + $data = json_encode($data->getEventData()); + } else { + $data = 'null'; + } + + $form = new AphrontFormView(); + $form + ->setUser($user) + ->appendChild( + id(new AphrontFormStaticControl()) + ->setLabel('ID') + ->setValue($event->getID())) + ->appendChild( + id(new AphrontFormStaticControl()) + ->setLabel('Type') + ->setValue($event->getType())) + ->appendChild( + id(new AphrontFormTextAreaControl()) + ->setDisabled(true) + ->setLabel('Data') + ->setValue($data)) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->addCancelButton('/daemon/timeline/')); + + $panel = new AphrontPanelView(); + $panel->setHeader('Event'); + $panel->setWidth(AphrontPanelView::WIDTH_FORM); + $panel->appendChild($form); + + return $this->buildStandardPageResponse( + $panel, + array( + 'title' => 'Timeline Event', + )); + } + +} diff --git a/src/applications/daemon/controller/timelineevent/__init__.php b/src/applications/daemon/controller/timelineevent/__init__.php new file mode 100644 index 0000000000..5423d87959 --- /dev/null +++ b/src/applications/daemon/controller/timelineevent/__init__.php @@ -0,0 +1,20 @@ +diffusionRequest; + + + + + $detail_panel = new AphrontPanelView(); + $detail_panel->setHeader('Revision Detail'); + $detail_panel->appendChild('
'.$drequest->getCommit().'
'); + + $change_table = new DiffusionCommitChangeTableView(); + $change_table->setDiffusionRequest($drequest); + $change_table->setPathChanges(array()); + + $change_panel = new AphrontPanelView(); + $change_panel->setHeader('Changes'); + $change_panel->appendChild($change_table); + + $change_list = + '
'. + '(list of changes goes here)'. + '
'; + + return $this->buildStandardPageResponse( + array( + $detail_panel, + $change_panel, + $change_list, + ), + array( + 'title' => 'Diffusion', + )); + } + +} diff --git a/src/applications/diffusion/controller/commit/__init__.php b/src/applications/diffusion/controller/commit/__init__.php new file mode 100644 index 0000000000..8d10609002 --- /dev/null +++ b/src/applications/diffusion/controller/commit/__init__.php @@ -0,0 +1,14 @@ +request = $request; + return $this; + } + + public function setPathChanges(array $path_changes) { + $this->pathChanges = $path_changes; + return $this; + } + + public function render() { + $rows = array(); + foreach ($this->pathChanges as $change) { + $rows[] = array( + 'browse', + 'whatever', + $change->getPath(), // TODO: link + // TODO: etc etc + ); + } + + $view = new AphrontTableView($rows); + $view->setHeaders( + array( + 'History', + 'Change', + 'Path', + )); + $view->setColumnClasses( + array( + '', + '', + 'wide', + )); + $view->setNoDataString('This change has not been fully parsed yet.'); + + return $view->render(); + } + +} diff --git a/src/applications/repository/daemon/commitdiscovery/base/PhabricatorRepositoryCommitDiscoveryDaemon.php b/src/applications/repository/daemon/commitdiscovery/base/PhabricatorRepositoryCommitDiscoveryDaemon.php index 9defcdd53d..b3f42e094a 100644 --- a/src/applications/repository/daemon/commitdiscovery/base/PhabricatorRepositoryCommitDiscoveryDaemon.php +++ b/src/applications/repository/daemon/commitdiscovery/base/PhabricatorRepositoryCommitDiscoveryDaemon.php @@ -20,6 +20,7 @@ abstract class PhabricatorRepositoryCommitDiscoveryDaemon extends PhabricatorRepositoryDaemon { private $repository; + private $commitCache = array(); final protected function getRepository() { return $this->repository; @@ -40,6 +41,56 @@ abstract class PhabricatorRepositoryCommitDiscoveryDaemon } } + protected function isKnownCommit($target) { + if (isset($this->commitCache[$target])) { + return true; + } + + $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere( + 'repositoryPHID = %s AND commitIdentifier = %s', + $this->getRepository()->getPHID(), + $target); + + if (!$commit) { + return false; + } + + $this->commitCache[$target] = true; + while (count($this->commitCache) > 16) { + array_shift($this->commitCache); + } + + return true; + } + + protected function recordCommit($commit_identifier, $epoch) { + $repository = $this->getRepository(); + + $commit = new PhabricatorRepositoryCommit(); + $commit->setRepositoryPHID($repository->getPHID()); + $commit->setCommitIdentifier($commit_identifier); + $commit->setEpoch($epoch); + + try { + $commit->save(); + $event = new PhabricatorTimelineEvent( + 'cmit', + array( + 'id' => $commit->getID(), + )); + $event->recordEvent(); + + $this->commitCache[$commit_identifier] = true; + } catch (AphrontQueryDuplicateKeyException $ex) { + // Ignore. This can happen because we discover the same new commit + // more than once when looking at history, or because of races or + // data inconsistency or cosmic radiation; in any case, we're still + // in a good state if we ignore the failure. + } + + $this->stillWorking(); + } + abstract protected function discoverCommits(); } diff --git a/src/applications/repository/daemon/commitdiscovery/base/__init__.php b/src/applications/repository/daemon/commitdiscovery/base/__init__.php index b48312c05a..cde21de298 100644 --- a/src/applications/repository/daemon/commitdiscovery/base/__init__.php +++ b/src/applications/repository/daemon/commitdiscovery/base/__init__.php @@ -7,6 +7,10 @@ phutil_require_module('phabricator', 'applications/repository/daemon/base'); +phutil_require_module('phabricator', 'applications/repository/storage/commit'); +phutil_require_module('phabricator', 'infrastructure/daemon/timeline/storage/event'); + +phutil_require_module('phutil', 'utils'); phutil_require_source('PhabricatorRepositoryCommitDiscoveryDaemon.php'); diff --git a/src/applications/repository/daemon/commitdiscovery/git/PhabricatorRepositoryGitCommitDiscoveryDaemon.php b/src/applications/repository/daemon/commitdiscovery/git/PhabricatorRepositoryGitCommitDiscoveryDaemon.php index 2c9e077b0c..9d8e9e746e 100644 --- a/src/applications/repository/daemon/commitdiscovery/git/PhabricatorRepositoryGitCommitDiscoveryDaemon.php +++ b/src/applications/repository/daemon/commitdiscovery/git/PhabricatorRepositoryGitCommitDiscoveryDaemon.php @@ -19,17 +19,14 @@ class PhabricatorRepositoryGitCommitDiscoveryDaemon extends PhabricatorRepositoryCommitDiscoveryDaemon { - private $lastCommit; - private $commitCache = array(); - protected function discoverCommits() { // NOTE: PhabricatorRepositoryGitPullDaemon does the actual pulls, this // just parses HEAD. $repository = $this->getRepository(); - // TODO: this should be a constant somewhere - if ($repository->getVersionControlSystem() != 'git') { + $vcs = $repository->getVersionControlSystem(); + if ($vcs != PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) { throw new Exception("Repository is not a git repository."); } @@ -41,12 +38,10 @@ class PhabricatorRepositoryGitCommitDiscoveryDaemon $repo_base); $commit = trim($commit); - if ($commit === $this->lastCommit || - $this->isKnownCommit($commit)) { + if ($this->isKnownCommit($commit)) { return false; } - $this->lastCommit = $commit; $this->discoverCommit($commit); return true; @@ -89,51 +84,12 @@ class PhabricatorRepositoryGitCommitDiscoveryDaemon $target); $epoch = trim($epoch); - $commit = new PhabricatorRepositoryCommit(); - $commit->setRepositoryPHID($this->getRepository()->getPHID()); - $commit->setCommitIdentifier($target); - $commit->setEpoch($epoch); - try { - $commit->save(); - $event = new PhabricatorTimelineEvent( - 'cmit', - array( - 'id' => $commit->getID(), - )); - $event->recordEvent(); - } catch (AphrontQueryDuplicateKeyException $ex) { - // Ignore. This can happen because we discover the same new commit - // more than once when looking at history, or because of races or - // data inconsistency or cosmic radiation; in any case, we're still - // in a good state if we ignore the failure. - } + $this->recordCommit($target, $epoch); + if (empty($insert)) { break; } - $this->stillWorking(); } } - private function isKnownCommit($target) { - if (isset($this->commitCache[$target])) { - return true; - } - - $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere( - 'repositoryPHID = %s AND commitIdentifier = %s', - $this->getRepository()->getPHID(), - $target); - - if (!$commit) { - return false; - } - - $this->commitCache[$target] = true; - if (count($this->commitCache) > 16) { - array_shift($this->commitCache); - } - - return true; - } - } diff --git a/src/applications/repository/daemon/commitdiscovery/git/__init__.php b/src/applications/repository/daemon/commitdiscovery/git/__init__.php index 91b37d309a..4404f788e1 100644 --- a/src/applications/repository/daemon/commitdiscovery/git/__init__.php +++ b/src/applications/repository/daemon/commitdiscovery/git/__init__.php @@ -6,12 +6,10 @@ +phutil_require_module('phabricator', 'applications/repository/constants/repositorytype'); phutil_require_module('phabricator', 'applications/repository/daemon/commitdiscovery/base'); -phutil_require_module('phabricator', 'applications/repository/storage/commit'); -phutil_require_module('phabricator', 'applications/timeline/storage/event'); phutil_require_module('phutil', 'future/exec'); -phutil_require_module('phutil', 'utils'); phutil_require_source('PhabricatorRepositoryGitCommitDiscoveryDaemon.php'); diff --git a/src/applications/repository/daemon/commitdiscovery/svn/PhabricatorRepositorySvnCommitDiscoveryDaemon.php b/src/applications/repository/daemon/commitdiscovery/svn/PhabricatorRepositorySvnCommitDiscoveryDaemon.php new file mode 100644 index 0000000000..44943d6fd3 --- /dev/null +++ b/src/applications/repository/daemon/commitdiscovery/svn/PhabricatorRepositorySvnCommitDiscoveryDaemon.php @@ -0,0 +1,77 @@ +getRepository(); + + $vcs = $repository->getVersionControlSystem(); + if ($vcs != PhabricatorRepositoryType::REPOSITORY_TYPE_SVN) { + throw new Exception("Repository is not a svn repository."); + } + + $repository_phid = $repository->getPHID(); + + $uri = $repository->getDetail('remote-uri'); + list($xml) = execx( + 'svn log --xml --non-interactive --quiet --limit 1 %s@HEAD', + $uri); + + // TODO: We need to slam the XML output into valid UTF-8. + + $log = new SimpleXMLElement($xml); + $entry = $log->logentry[0]; + $commit = (int)$entry['revision']; + + if ($this->isKnownCommit($commit)) { + return false; + } + + $this->discoverCommit($commit); + + return true; + } + + private function discoverCommit($commit) { + $discover = array(); + $largest_known = $commit - 1; + while ($largest_known > 0 && !$this->isKnownCommit($largest_known)) { + $largest_known--; + } + + $repository = $this->getRepository(); + $uri = $repository->getDetail('remote-uri'); + + for ($ii = $largest_known + 1; $ii <= $commit; $ii++) { + list($xml) = execx( + 'svn log --xml --non-interactive --quiet --limit 1 %s@%d', + $uri, + $ii); + $log = new SimpleXMLElement($xml); + $entry = $log->logentry[0]; + + $identifier = (int)$entry['revision']; + $epoch = (int)strtotime((string)$entry->date[0]); + + $this->recordCommit($identifier, $epoch); + } + } + +} diff --git a/src/applications/repository/daemon/commitdiscovery/svn/__init__.php b/src/applications/repository/daemon/commitdiscovery/svn/__init__.php new file mode 100644 index 0000000000..61d4b5a2af --- /dev/null +++ b/src/applications/repository/daemon/commitdiscovery/svn/__init__.php @@ -0,0 +1,15 @@ +getData(); + + if (!$data) { + // TODO: This event can't be processed, provide some way to + // communicate that? + continue; + } + + $commit = id(new PhabricatorRepositoryCommit())->load($data['id']); + if (!$commit) { + // TODO: Same as above. + continue; + } + + // TODO: Cache these. + $repository = id(new PhabricatorRepository())->loadOneWhere( + 'phid = %s', + $commit->getRepositoryPHID()); + + $vcs = $repository->getVersionControlSystem(); + switch ($vcs) { + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: + $class = 'PhabricatorRepositoryGitCommitMessageParserWorker'; + $task = new PhabricatorWorkerTask(); + $task->setTaskClass($class); + $task->setData($commit->getID()); + $task->save(); + break; + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: + $class = 'PhabricatorRepositorySvnCommitMessageParserWorker'; + $task = new PhabricatorWorkerTask(); + $task->setTaskClass($class); + $task->setData($commit->getID()); + $task->save(); + break; + default: + throw new Exception("Unknown repository type."); + } + + $this->stillWorking(); + } + sleep(1); + $this->stillWorking(); + } while (true); + } + +} diff --git a/src/applications/repository/daemon/committask/__init__.php b/src/applications/repository/daemon/committask/__init__.php new file mode 100644 index 0000000000..3e85d352f5 --- /dev/null +++ b/src/applications/repository/daemon/committask/__init__.php @@ -0,0 +1,19 @@ + false, + ) + parent::getConfiguration(); + } } diff --git a/src/applications/repository/storage/commitdata/__init__.php b/src/applications/repository/storage/commitdata/__init__.php new file mode 100644 index 0000000000..57fe6d1dcf --- /dev/null +++ b/src/applications/repository/storage/commitdata/__init__.php @@ -0,0 +1,12 @@ +getTaskData(); + if (!$commit_id) { + return; + } + + $commit = id(new PhabricatorRepositoryCommit())->load($commit_id); + + if (!$commit) { + // TODO: Communicate permanent failure? + return; + } + + $this->commit = $commit; + + $repository = id(new PhabricatorRepository())->loadOneWhere( + 'phid = %s', + $commit->getRepositoryPHID()); + + if (!$repository) { + return; + } + + return $this->parseCommit($repository, $commit); + } + + abstract protected function parseCommit( + PhabricatorRepository $repository, + PhabricatorRepositoryCommit $commit); + +} diff --git a/src/applications/repository/worker/base/__init__.php b/src/applications/repository/worker/base/__init__.php new file mode 100644 index 0000000000..2b6b8ed4d5 --- /dev/null +++ b/src/applications/repository/worker/base/__init__.php @@ -0,0 +1,16 @@ +establishConnection('w'); + + $result_map = $this->lookupPaths($paths); + + $missing_paths = array_fill_keys($paths, true); + $missing_paths = array_diff_key($missing_paths, $result_map); + $missing_paths = array_keys($missing_paths); + + if ($missing_paths) { + foreach (array_chunk($missing_paths, 512) as $path_chunk) { + $sql = array(); + foreach ($path_chunk as $path) { + $sql[] = qsprintf($conn_w, '(%s)', $path); + } + queryfx( + $conn_w, + 'INSERT INTO %T (path) VALUES %Q', + PhabricatorRepository::TABLE_PATH, + implode(', ', $sql)); + } + $result_map += $this->lookupPaths($missing_paths); + } + + return $result_map; + } + + private function lookupPaths(array $paths) { + $repository = new PhabricatorRepository(); + $conn_w = $repository->establishConnection('w'); + + $result_map = array(); + foreach (array_chunk($paths, 512) as $path_chunk) { + $chunk_map = queryfx_all( + $conn_w, + 'SELECT path, id FROM %T WHERE path IN (%Ls)', + PhabricatorRepository::TABLE_PATH, + $path_chunk); + foreach ($chunk_map as $row) { + $result_map[$row['path']] = $row['id']; + } + } + return $result_map; + } + + +} diff --git a/src/applications/repository/worker/commitchangeparser/base/__init__.php b/src/applications/repository/worker/commitchangeparser/base/__init__.php new file mode 100644 index 0000000000..08e8c51252 --- /dev/null +++ b/src/applications/repository/worker/commitchangeparser/base/__init__.php @@ -0,0 +1,15 @@ +getDetail('local-path'); + + list($raw) = execx( + '(cd %s && git log -n1 -M -C -B --find-copies-harder --raw -t '. + '--abbrev=40 --pretty=format: %s)', + $local_path, + $commit->getCommitIdentifier()); + + $changes = array(); + $move_away = array(); + $copy_away = array(); + $lines = explode("\n", $raw); + foreach ($lines as $line) { + if (!strlen(trim($line))) { + continue; + } + list($old_mode, $new_mode, + $old_hash, $new_hash, + $more_stuff) = preg_split('/ +/', $line); + + // We may only have two pieces here. + list($action, $src_path, $dst_path) = array_merge( + explode("\t", $more_stuff), + array(null)); + + $old_mode = intval($old_mode, 8); + $new_mode = intval($new_mode, 8); + + $file_type = DifferentialChangeType::FILE_NORMAL; + if ($new_mode & 040000) { + $file_type = DifferentialChangeType::FILE_DIRECTORY; + } else if ($new_mode & 0120000) { + $file_type = DifferentialChangeType::FILE_SYMLINK; + } + + // TODO: We can detect binary changes as git does, through a combination + // of running 'git check-attr' for stuff like 'binary', 'merge' or 'diff', + // and by falling back to inspecting the first 8,000 characters of the + // buffer for null bytes (this is seriously git's algorithm, see + // buffer_is_binary() in xdiff-interface.c). + + $change_type = null; + $change_path = $src_path; + $change_target = null; + + switch ($action[0]) { + case 'A': + $change_type = DifferentialChangeType::TYPE_ADD; + break; + case 'D': + $change_type = DifferentialChangeType::TYPE_DELETE; + break; + case 'C': + $change_type = DifferentialChangeType::TYPE_COPY_HERE; + $change_path = $dst_path; + $change_target = $src_path; + $copy_away[$change_target][] = $change_path; + break; + case 'R': + $change_type = DifferentialChangeType::TYPE_MOVE_HERE; + $change_path = $dst_path; + $change_target = $src_path; + $move_away[$change_target][] = $change_path; + break; + case 'M': + $change_type = DifferentialChangeType::TYPE_CHANGE; + break; + default: + throw new Exception("Failed to parse line '{$line}'."); + } + + $changes[$change_path] = array( + 'repositoryID' => $repository->getID(), + 'commitID' => $commit->getID(), + + 'path' => $change_path, + 'changeType' => $change_type, + 'fileType' => $file_type, + 'isDirect' => true, + 'commitSequence' => $commit->getEpoch(), + + 'targetPath' => $change_target, + 'targetCommitID' => $change_target ? $commit->getID() : null, + ); + } + + foreach ($copy_away as $change_path => $destinations) { + if (isset($move_away[$change_path])) { + $change_type = DifferentialChangeType::TYPE_MULTICOPY; + $is_direct = true; + unset($move_away[$change_path]); + } else { + $change_type = DifferentialChangeType::TYPE_COPY_AWAY; + $is_direct = false; + } + + $reference = $changes[reset($destinations)]; + + $changes[$change_path] = array( + 'repositoryID' => $repository->getID(), + 'commitID' => $commit->getID(), + + 'path' => $change_path, + 'changeType' => $change_type, + 'fileType' => $reference['fileType'], + 'isDirect' => $is_direct, + 'commitSequence' => $commit->getEpoch(), + + 'targetPath' => null, + 'targetCommitID' => null, + ); + } + + foreach ($move_away as $change_path => $destinations) { + $reference = $changes[reset($destinations)]; + + $changes[$change_path] = array( + 'repositoryID' => $repository->getID(), + 'commitID' => $commit->getID(), + + 'path' => $change_path, + 'changeType' => DifferentialChangeType::TYPE_MOVE_AWAY, + 'fileType' => $reference['fileType'], + 'isDirect' => true, + 'commitSequence' => $commit->getEpoch(), + + 'targetPath' => null, + 'targetCommitID' => null, + ); + } + + $paths = array(); + foreach ($changes as $change) { + $paths[$change['path']] = true; + if ($change['targetPath']) { + $paths[$change['targetPath']] = true; + } + } + + $path_map = $this->lookupOrCreatePaths(array_keys($paths)); + + foreach ($changes as $key => $change) { + $changes[$key]['pathID'] = $path_map[$change['path']]; + if ($change['targetPath']) { + $changes[$key]['targetPathID'] = $path_map[$change['targetPath']]; + } else { + $changes[$key]['targetPathID'] = null; + } + } + + $conn_w = $repository->establishConnection('w'); + + $changes_sql = array(); + foreach ($changes as $change) { + $values = array( + (int)$change['repositoryID'], + (int)$change['pathID'], + (int)$change['commitID'], + $change['targetPathID'] + ? (int)$change['targetPathID'] + : 'null', + $change['targetCommitID'] + ? (int)$change['targetCommitID'] + : 'null', + (int)$change['changeType'], + (int)$change['fileType'], + (int)$change['isDirect'], + (int)$change['commitSequence'], + ); + $changes_sql[] = '('.implode(', ', $values).')'; + } + + queryfx( + $conn_w, + 'DELETE FROM %T WHERE commitID = %d', + PhabricatorRepository::TABLE_PATHCHANGE, + $commit->getID()); + foreach (array_chunk($changes_sql, 256) as $sql_chunk) { + queryfx( + $conn_w, + 'INSERT INTO %T + (repositoryID, pathID, commitID, targetPathID, targetCommitID, + changeType, fileType, isDirect, commitSequence) + VALUES %Q', + PhabricatorRepository::TABLE_PATHCHANGE, + implode(', ', $sql_chunk)); + } + } + +} diff --git a/src/applications/repository/worker/commitchangeparser/git/__init__.php b/src/applications/repository/worker/commitchangeparser/git/__init__.php new file mode 100644 index 0000000000..6bc6d8d55e --- /dev/null +++ b/src/applications/repository/worker/commitchangeparser/git/__init__.php @@ -0,0 +1,17 @@ +commit; + + $data = id(new PhabricatorRepositoryCommitData())->loadOneWhere( + 'commitID = %d', + $commit->getID()); + if (!$data) { + $data = new PhabricatorRepositoryCommitData(); + } + $data->setCommitID($commit->getID()); + $data->setAuthorName($author); + $data->setCommitMessage($message); + $data->save(); + } + +} diff --git a/src/applications/repository/worker/commitmessageparser/base/__init__.php b/src/applications/repository/worker/commitmessageparser/base/__init__.php new file mode 100644 index 0000000000..1add9e0528 --- /dev/null +++ b/src/applications/repository/worker/commitmessageparser/base/__init__.php @@ -0,0 +1,15 @@ +getDetail('local-path'); + + list($info) = execx( + '(cd %s && git log -n 1 --pretty=format:%%an%%x00%%B %s)', + $local_path, + $commit->getCommitIdentifier()); + + // TODO: Need to slam UTF8? + + list($author, $message) = explode("\0", $info); + + $this->updateCommitData($author, $message); + + $task = new PhabricatorWorkerTask(); + $task->setTaskClass('PhabricatorRepositoryGitCommitChangeParserWorker'); + $task->setData($commit->getID()); + $task->save(); + } + +} diff --git a/src/applications/repository/worker/commitmessageparser/git/__init__.php b/src/applications/repository/worker/commitmessageparser/git/__init__.php new file mode 100644 index 0000000000..f139ac2819 --- /dev/null +++ b/src/applications/repository/worker/commitmessageparser/git/__init__.php @@ -0,0 +1,15 @@ +getDetail('remote-uri'); + + list($xml) = execx( + 'svn log --xml --limit 1 --non-interactive %s@%d', + $uri, + $commit->getCommitIdentifier()); + + // TODO: Need to slam UTF8. + + $log = new SimpleXMLElement($xml); + $entry = $log->logentry[0]; + + $author = (string)$entry->author; + $message = (string)$entry->msg; + + $this->updateCommitData($author, $message); + } + +} diff --git a/src/applications/repository/worker/commitmessageparser/svn/__init__.php b/src/applications/repository/worker/commitmessageparser/svn/__init__.php new file mode 100644 index 0000000000..e8bb732e78 --- /dev/null +++ b/src/applications/repository/worker/commitmessageparser/svn/__init__.php @@ -0,0 +1,14 @@ +establishConnection('r'), 'SELECT event.*, event_data.eventData eventData - FROM %T event WHERE event.id > %d AND event.type in (%Ls) + FROM %T event LEFT JOIN %T event_data ON event_data.eventID = event.id + WHERE event.id > %d AND event.type in (%Ls) ORDER BY event.id ASC LIMIT %d', $event->getTableName(), + $event_data->getTableName(), $this->cursor->getPosition(), $this->eventTypes, - $event_data->getTableName(), self::LOAD_CHUNK_SIZE); $events = $event->loadAllFromArray($raw_data); diff --git a/src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php b/src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php index 6a1d379d5f..a55375c40b 100644 --- a/src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php +++ b/src/infrastructure/daemon/timeline/storage/cursor/PhabricatorTimelineCursor.php @@ -21,6 +21,10 @@ class PhabricatorTimelineCursor extends PhabricatorTimelineDAO { protected $name; protected $position; + public function getIDKey() { + return 'name'; + } + public function getConfiguration() { return array( self::CONFIG_IDS => self::IDS_MANUAL, @@ -28,4 +32,11 @@ class PhabricatorTimelineCursor extends PhabricatorTimelineDAO { ) + parent::getConfiguration(); } + public function shouldInsertWhenSaved() { + if ($this->position == 0) { + return true; + } + return false; + } + } diff --git a/src/infrastructure/daemon/workers/storage/task/PhabricatorWorkerTask.php b/src/infrastructure/daemon/workers/storage/task/PhabricatorWorkerTask.php index f41b3ceba2..9d980095db 100644 --- a/src/infrastructure/daemon/workers/storage/task/PhabricatorWorkerTask.php +++ b/src/infrastructure/daemon/workers/storage/task/PhabricatorWorkerTask.php @@ -21,11 +21,11 @@ class PhabricatorWorkerTask extends PhabricatorWorkerDAO { protected $taskClass; protected $leaseOwner; protected $leaseExpires; - protected $priority; protected $failureCount; private $serverTime; private $localTime; + private $data; public function getConfiguration() { return array( @@ -53,8 +53,30 @@ class PhabricatorWorkerTask extends PhabricatorWorkerDAO { } } - return parent::save(); + $is_new = !$this->getID(); + if ($is_new) { + $this->failureCount = 0; + } + + $ret = parent::save(); + + if ($is_new && $this->data) { + $data = new PhabricatorWorkerTaskData(); + $data->setTaskID($this->getID()); + $data->setData($this->data); + $data->save(); + } + + return $ret; } + public function setData($data) { + $this->data = $data; + return $this; + } + + public function getData() { + return $this->data; + } } diff --git a/src/infrastructure/daemon/workers/storage/task/__init__.php b/src/infrastructure/daemon/workers/storage/task/__init__.php index 933817be3c..0a7539275a 100644 --- a/src/infrastructure/daemon/workers/storage/task/__init__.php +++ b/src/infrastructure/daemon/workers/storage/task/__init__.php @@ -7,6 +7,7 @@ phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/base'); +phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/taskdata'); phutil_require_source('PhabricatorWorkerTask.php'); diff --git a/src/infrastructure/daemon/workers/taskmaster/PhabricatorTaskmasterDaemon.php b/src/infrastructure/daemon/workers/taskmaster/PhabricatorTaskmasterDaemon.php index 27731b1f3d..4a5d202312 100644 --- a/src/infrastructure/daemon/workers/taskmaster/PhabricatorTaskmasterDaemon.php +++ b/src/infrastructure/daemon/workers/taskmaster/PhabricatorTaskmasterDaemon.php @@ -30,14 +30,21 @@ class PhabricatorTaskmasterDaemon extends PhabricatorDaemon { queryfx( $conn_w, 'UPDATE %T SET leaseOwner = %s, leaseExpires = UNIX_TIMESTAMP() + 15 - WHERE leaseOwner IS NULL - OR leaseExpires < UNIX_TIMESTAMP() - ORDER BY leaseOwner IS NULL, failureCount, priority - LIMIT 1', + WHERE leaseOwner IS NULL LIMIT 1', $task_table->getTableName(), $lease_ownership_name); $rows = $conn_w->getAffectedRows(); + if (!$rows) { + $rows = queryfx( + $conn_w, + 'UPDATE %T SET leaseOwner = %s, leaseExpires = UNIX_TIMESTAMP() + 15 + WHERE leaseExpires < UNIX_TIMESTAMP() LIMIT 1', + $task_table->getTableName(), + $lease_ownership_name); + $rows = $conn_w->getAffectedRows(); + } + if ($rows) { $data = queryfx_all( $conn_w, @@ -91,7 +98,7 @@ class PhabricatorTaskmasterDaemon extends PhabricatorDaemon { queryfx( $conn_w, 'DELETE FROM %T WHERE taskID = %d', - $taskdata_table, + $taskdata_table->getTableName(), $task->getID()); } } catch (Exception $ex) {