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

Add followers to Asana diff tasks silently

Summary: Ref T2852. Asana is launching some kind of silent follow thing today; I don't know what the API is but it's probably something like this. I'll update this to actually make the right call once the call exists, this is mostly just a placeholder so I don't forget about it.

Test Plan: None yet, this API isn't documented or live and doesn't work yet so it can't be tested.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran, moskov

Maniphest Tasks: T2852

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

+62 -22
+62 -22
src/applications/doorkeeper/worker/DoorkeeperFeedWorkerAsana.php
··· 221 221 222 222 $main_data = $this->getAsanaTaskData($object) + array( 223 223 'assignee' => $owner_asana_id, 224 - 'followers' => $all_asana_ids, 225 224 ); 226 225 227 226 $extra_data = array(); ··· 251 250 // TODO: This probably breaks, very rarely, on 32-bit systems. 252 251 if ($edge_cursor <= $story->getChronologicalKey()) { 253 252 $this->log("Updating main task.\n"); 254 - 255 - // We need to synchronize follower data separately. 256 - $put_data = $main_data; 257 - unset($put_data['followers']); 253 + $task_id = $parent_ref->getObjectID(); 258 254 259 255 $this->makeAsanaAPICall( 260 256 $oauth_token, 261 257 "tasks/".$parent_ref->getObjectID(), 262 258 'PUT', 263 - $put_data); 264 - 265 - // To synchronize follower data, just add all the followers. The task 266 - // might have additional followers, but we can't really tell how they 267 - // got there: were they CC'd and then unsubscribed, or did they 268 - // manually follow the task? Assume the latter since it's easier and 269 - // less destructive and the former is rare. 270 - 271 - if ($main_data['followers']) { 272 - $this->makeAsanaAPICall( 273 - $oauth_token, 274 - 'tasks/'.$parent_ref->getObjectID().'/addFollowers', 275 - 'POST', 276 - array( 277 - 'followers' => $main_data['followers'], 278 - )); 279 - } 259 + $main_data); 280 260 } else { 281 261 $this->log( 282 262 "Skipping main task update, cursor is ahead of the story.\n"); ··· 304 284 // we should not overwrite their choices. 305 285 'assignee_status' => 'later', 306 286 ) + $main_data); 287 + 307 288 $parent_ref = $this->newRefFromResult( 308 289 DoorkeeperBridgeAsana::OBJTYPE_TASK, 309 290 $parent); 291 + 310 292 311 293 $extra_data = array( 312 294 'workspace' => $workspace_id, 313 295 ); 314 296 } 297 + 298 + // Synchronize main task followers. 299 + 300 + $task_id = $parent_ref->getObjectID(); 301 + 302 + // Reviewers are added as followers of the parent task silently, because 303 + // they receive a notification when they are assigned as the owner of their 304 + // subtask, so the follow notification is redundant / non-actionable. 305 + $silent_followers = array_select_keys($phid_aid_map, $active_phids) + 306 + array_select_keys($phid_aid_map, $passive_phids); 307 + $silent_followers = array_values($silent_followers); 308 + 309 + // CCs are added as followers of the parent task with normal notifications, 310 + // since they won't get a secondary subtask notification. 311 + $noisy_followers = array_select_keys($phid_aid_map, $follow_phids); 312 + $noisy_followers = array_values($noisy_followers); 313 + 314 + // To synchronize follower data, just add all the followers. The task might 315 + // have additional followers, but we can't really tell how they got there: 316 + // were they CC'd and then unsubscribed, or did they manually follow the 317 + // task? Assume the latter since it's easier and less destructive and the 318 + // former is rare. To be fully consistent, we should enumerate followers 319 + // and remove unknown followers, but that's a fair amount of work for little 320 + // benefit, and creates a wider window for race conditions. 321 + 322 + // Add the silent followers first so that a user who is both a reviewer and 323 + // a CC gets silently added and then implicitly skipped by then noisy add. 324 + // They will get a subtask notification. 325 + $this->addFollowers($oauth_token, $task_id, $silent_followers, true); 326 + $this->addFollowers($oauth_token, $task_id, $noisy_followers); 315 327 316 328 $dst_phid = $parent_ref->getExternalObject()->getPHID(); 317 329 ··· 654 666 $count = $task->getFailureCount(); 655 667 return (5 * 60) * pow(8, $count); 656 668 } 669 + 670 + private function addFollowers( 671 + $oauth_token, 672 + $task_id, 673 + array $followers, 674 + $silent = false) { 675 + 676 + if (!$followers) { 677 + return; 678 + } 679 + 680 + $data = array( 681 + 'followers' => $followers, 682 + ); 683 + 684 + // NOTE: This uses a currently-undocumented API feature to suppress the 685 + // follow notifications. 686 + if ($silent) { 687 + $data['silent'] = true; 688 + } 689 + 690 + $this->makeAsanaAPICall( 691 + $oauth_token, 692 + "tasks/{$task_id}/addFollowers", 693 + 'POST', 694 + $data); 695 + } 696 + 657 697 658 698 }