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

Make workboard real-time updates mostly work

Summary:
Depends on D20654. Ref T4900. When a task is edited, emit a "workboards" event for all boards it appears on (in a future change, this should also include all boards it //previously// appeared on, and all parents of both sets of boards -- but I'm just getting things working for now).

When we receive a "workboards" event, check if the visible board should be updated.

Aphlict has a complicated intra-window leader/follower election system which could let us process this update event exactly once no matter how many windows a user has open with the same workboard. I'm not trying to do any of this since it seems fairly rare. It makes sense for events like "you have new notifications" where we don't want to generate 100 Ajax calls if the user has 100 windows open, but very few users seem likely to have 100 copies of the same workboard open.

Test Plan:
- Ran `bin/aphlict debug`.
- Opened workboard A in two windows, X and Y.
- Edited and moved tasks in window X.
- Saw "workboards" messages in the Aphlict log.
- Saw window Y update in nearly-real-time (locally, this is fast enough that it feels instantaneous).

Then:

- Stopped the Aphlcit server.
- Edited a task.
- Started the Aphlict server.
- Saw window Y update after a few moments (i.e., update in response to a reconnect).

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T4900

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

+73 -14
+14 -14
resources/celerity/map.php
··· 412 412 'rsrc/js/application/phortune/phortune-credit-card-form.js' => 'd12d214f', 413 413 'rsrc/js/application/policy/behavior-policy-control.js' => '0eaa33a9', 414 414 'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '9347f172', 415 - 'rsrc/js/application/projects/WorkboardBoard.js' => '19df903f', 415 + 'rsrc/js/application/projects/WorkboardBoard.js' => '75727403', 416 416 'rsrc/js/application/projects/WorkboardCard.js' => '0392a5d8', 417 417 'rsrc/js/application/projects/WorkboardCardTemplate.js' => '84f82dad', 418 418 'rsrc/js/application/projects/WorkboardColumn.js' => 'c3d24e63', ··· 743 743 'javelin-view-renderer' => '9aae2b66', 744 744 'javelin-view-visitor' => '308f9fe4', 745 745 'javelin-websocket' => 'fdc13e4e', 746 - 'javelin-workboard-board' => '19df903f', 746 + 'javelin-workboard-board' => '75727403', 747 747 'javelin-workboard-card' => '0392a5d8', 748 748 'javelin-workboard-card-template' => '84f82dad', 749 749 'javelin-workboard-column' => 'c3d24e63', ··· 1030 1030 '17b71bbc' => array( 1031 1031 'phui-theme-css', 1032 1032 ), 1033 - '19df903f' => array( 1034 - 'javelin-install', 1035 - 'javelin-dom', 1036 - 'javelin-util', 1037 - 'javelin-stratcom', 1038 - 'javelin-workflow', 1039 - 'phabricator-draggable-list', 1040 - 'javelin-workboard-column', 1041 - 'javelin-workboard-header-template', 1042 - 'javelin-workboard-card-template', 1043 - 'javelin-workboard-order-template', 1044 - ), 1045 1033 '1b6acc2a' => array( 1046 1034 'javelin-magical-init', 1047 1035 'javelin-util', ··· 1560 1548 'javelin-dom', 1561 1549 'javelin-uri', 1562 1550 'javelin-request', 1551 + ), 1552 + 75727403 => array( 1553 + 'javelin-install', 1554 + 'javelin-dom', 1555 + 'javelin-util', 1556 + 'javelin-stratcom', 1557 + 'javelin-workflow', 1558 + 'phabricator-draggable-list', 1559 + 'javelin-workboard-column', 1560 + 'javelin-workboard-header-template', 1561 + 'javelin-workboard-card-template', 1562 + 'javelin-workboard-order-template', 1563 1563 ), 1564 1564 '78bc5d94' => array( 1565 1565 'javelin-behavior',
+29
src/applications/maniphest/editor/ManiphestTransactionEditor.php
··· 859 859 return array_values($phid_list); 860 860 } 861 861 862 + 863 + protected function didApplyTransactions($object, array $xactions) { 864 + // TODO: This should include projects which the object was previously 865 + // associated with but no longer is (so it can be removed from those 866 + // boards) but currently does not. 867 + 868 + $edge_query = id(new PhabricatorEdgeQuery()) 869 + ->withSourcePHIDs(array($object->getPHID())) 870 + ->withEdgeTypes( 871 + array( 872 + PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, 873 + )); 874 + 875 + $edge_query->execute(); 876 + 877 + $project_phids = $edge_query->getDestinationPHIDs(); 878 + 879 + if ($project_phids) { 880 + $data = array( 881 + 'type' => 'workboards', 882 + 'subscribers' => $project_phids, 883 + ); 884 + 885 + PhabricatorNotificationClient::tryToPostMessage($data); 886 + } 887 + 888 + return $xactions; 889 + } 890 + 862 891 }
+30
webroot/rsrc/js/application/projects/WorkboardBoard.js
··· 136 136 .setHandler(on_reload) 137 137 .register(); 138 138 139 + var board_phid = this.getPHID(); 140 + 141 + JX.Stratcom.listen('aphlict-server-message', null, function(e) { 142 + var message = e.getData(); 143 + 144 + if (message.type != 'workboards') { 145 + return; 146 + } 147 + 148 + // Check if this update notification is about the currently visible 149 + // board. If it is, update the board state. 150 + 151 + var found_board = false; 152 + for (var ii = 0; ii < message.subscribers.length; ii++) { 153 + var subscriber_phid = message.subscribers[ii]; 154 + if (subscriber_phid === board_phid) { 155 + found_board = true; 156 + break; 157 + } 158 + } 159 + 160 + if (found_board) { 161 + on_reload(); 162 + } 163 + }); 164 + 165 + JX.Stratcom.listen('aphlict-reconnect', null, function(e) { 166 + on_reload(); 167 + }); 168 + 139 169 for (var k in this._columns) { 140 170 this._columns[k].redraw(); 141 171 }