Page MenuHomePhabricator

Converting badge recipients from Edge to BadgeAward table
ClosedPublic

Authored by lpriestley on Jan 13 2016, 7:38 PM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Jan 28, 2:15 PM
Unknown Object (File)
Fri, Jan 24, 8:17 PM
Unknown Object (File)
Fri, Jan 24, 11:11 AM
Unknown Object (File)
Fri, Jan 24, 11:11 AM
Unknown Object (File)
Fri, Jan 24, 11:11 AM
Unknown Object (File)
Fri, Jan 24, 11:11 AM
Unknown Object (File)
Fri, Jan 24, 11:11 AM
Unknown Object (File)
Fri, Jan 24, 11:11 AM
Subscribers

Details

Summary

Ref T8996, Convert badge recipients from Edges to actual BadgeAward objects

Test Plan

Create badge, award it to recipient. Make sure adding/removing recipients works. (Still need to migrate exisiting recipients to new table and need to create activity feed blurbs)

Diff Detail

Repository
rP Phabricator
Branch
badgesaward
Lint
Lint Passed
Unit
Tests Passed
Build Status
Buildable 11269
Build 14002: Run Core Tests
Build 14001: arc lint + arc unit

Event Timeline

lpriestley retitled this revision from to Converting badge recipients from Edge to BadgeAward table.
lpriestley updated this object.
lpriestley edited the test plan for this revision. (Show Details)
lpriestley added a reviewer: epriestley.

Nice, this looks good. I caught a few things inline (mostly style/modernization stuff). Once this is ready to go I'll write you the migration for it.

src/applications/badges/controller/PhabricatorBadgesEditRecipientsController.php
29–30

I think this won't work -- if something is being removed, we need to apply two separate transactions (one TYPE_AWARD to award badges, one TYPE_REVOKE to revoke them). But I'm also not sure if this code is reachable, so we might be able to just delete it

src/applications/badges/editor/PhabricatorBadgesEditor.php
124

It would be better for this transaction type to take a list of PHIDs instead of a single PHID, so future UI or API callers can bulk-remove a bunch of awards at once.

128–130

For consistency with TYPE_AWARD, you might want to remove the deleted awards from the list and then re-attach the new, smaller list with attachAwards(), so the attached awards are always up to date.

src/applications/badges/query/PhabricatorBadgesAwardQuery.php
22

I don't understand the [1] here, and it seems like it shouldn't work?

49–62

Prefer to implement newResultObject() and then implement loadPage() as:

return $this->loadStandardPage($this->newResultObject());

This has the same effect, but is a little simpler.

64

There's a slightly newer style for these which is preferred -- you should implement buildWhereClauseParts() instead of buildWhereClause(). You can search for other implementations.

The implementation is nearly the same, you just don't have to call buildPagingClause() or formatWhereClause(), and the infrastructure can do some other kinds of work for you (which aren't relevant here) automatically.

src/applications/badges/query/PhabricatorBadgesQuery.php
62–64

You should be able to omit either the array() default to idx() or the explicit === null check, since they both do the same thing (give you an array() value if the key is missing).

src/applications/badges/storage/PhabricatorBadgesAward.php
17

I think this can have a PhabricatorBadgesBadge typehint?

19–22

$app appears unused.

60–66

BadgesBadge should have new code in its destroyObjectPermanently() method to remove all awards, too (so when you destroy a badge, you destroy all the awards of that badge).

epriestley edited edge metadata.
This revision now requires changes to proceed.Jan 14 2016, 1:47 PM
src/applications/badges/query/PhabricatorBadgesAwardQuery.php
22

Otherwise I get a:

Argument 1 passed to PhabricatorBadgesAward::attachBadge() must be an instance of PhabricatorBadgesBadge, array given, called in /Users/lkassianik/phacility/phabricator/src/applications/badges/query/PhabricatorBadgesAwardQuery.php on line 27
src/applications/badges/query/PhabricatorBadgesAwardQuery.php
18

Aha!

Probably rename $query to $badges, then this should be mpull($badges, null, 'getPHID'), not mgroup(...). That should solve the [1] issue.

lpriestley edited edge metadata.
lpriestley marked 11 inline comments as done.

Updating diff with feedback

epriestley edited edge metadata.

This looks great. I caught a few more little things, but looks solid otherwise.

resources/sql/autopatches/20160102.badges.award.sql
9–10

We should also have a separate key on just recipientPHID. Maybe call this key_badge and the other one key_recipient:

UNIQUE KEY `key_badge` (badgePHID, recipientPHID),
KEY `key_recipient` (recipientPHID)

We issue two types of queries: on the badge page, we issue ... WHERE badgePHID = X to find all awards of a particular badge.

On profile pages, we issue ... WHERE recipientPHID = X to find all badges a particular user has been awarded.

MySQL can use any prefix of a key to improve query performance, but the <badgePHID, recipientPHID> key doesn't have a useful prefix for optimizing the recipientPHID = X case.

Adding a second key will let both kinds of queries use a key, and execute quickly.

src/applications/badges/editor/PhabricatorBadgesEditor.php
50

I'm surprised this works if you award a badge which has already been awarded to at least one user.

I'd expect this to return a list of objects, which can not be JSON serialized and thus can not be stored in the database, so I'd expect this to produce an exception like "Unable to JSON encode transaction old value" or similar (possibly something less specific).

Instead, this should probably just return the list of awardee PHIDs.

src/applications/badges/storage/PhabricatorBadgesAward.php
33–38

(When you fiddle with the keys, fiddle with this too.)

src/applications/badges/storage/PhabricatorBadgesBadge.php
200

I think this probably won't work -- use bin/remove destroy <phid> to destroy a badge with at least one award.

I'd expect you to get an error like "badges are not attached!", because the DestructionEngine does not know that you expect it to call needRecipients().

Instead, I'd just use PhabricatorBadgesAwardQuery explicitly to load the awards here.

202

This should be $engine->destroyObject($award); to make sure any related objects get cleaned up (in this case, there aren't any today).

This revision now requires changes to proceed.Mar 8 2016, 9:59 PM
lpriestley edited edge metadata.
lpriestley marked 5 inline comments as done.

Correcting how awards of a delete badge get wiped

This looks good to me, let me get you a migration for it.

Oh, it looks like there's an edge query in PHUITimelineView that this doesn't deal with. I'd expect that to prevent badges from appearing on timelines.

This should handle the migration (just drop it into autopatches/ as a new migration patch):

20160308.badgemigrate.sql
/* PhabricatorBadgeHasRecipientEdgeType::TYPECONST = 59 */

INSERT INTO {$NAMESPACE}_badges.badges_award
  (badgePHID, recipientPHID, awarderPHID, dateCreated, dateModified)
  SELECT src, dst, 'PHID-VOID-00000000000000000000', dateCreated, dateCreated
    FROM {$NAMESPACE}_badges.edge WHERE type = 59;
epriestley edited edge metadata.

Upshot:

  • Fix the remaining edge query in PHUITimelineView.
  • Add that migration (and run it to make sure I didn't break anything).

Then I think we're good to go.

This revision now requires changes to proceed.Mar 9 2016, 12:30 AM
lpriestley edited edge metadata.

Fixing timeline view to show badges under user icons

lpriestley edited edge metadata.

Migration script for badges

epriestley edited edge metadata.

Oh, I think you only got that error because you'd already used the new code to award some badges. That's fine, INSERT IGNORE ... is reasonable in this case anyway (it just makes us ignore rows which would fail to insert because of duplicate key errors).

I think I caught one more minor issue inline.

src/view/phui/PHUITimelineView.php
262

This probably needs to be idx($awards, $event->getAuthorPHID(), array()) because it's possible the author has no badges, and thus won't have an entry in the table.

I'd expect you to see an error if you look at a comment made by a user who has been awarded no badges.

This revision now requires changes to proceed.Mar 23 2016, 10:28 PM
lpriestley edited edge metadata.
lpriestley marked an inline comment as done.

Using correct way to find timeline event author badge award, in case author has no badge awards

epriestley edited edge metadata.

Caught a couple more issues.

src/applications/badges/storage/PhabricatorBadgesAward.php
28–32

Very minor, but these can be omitted because any column named somethingPHID defaults to phid as a type.

40

This key is improperly specified as unique, which prevents the same user from receiving more than one badge. To reproduce:

  • Make sure schema/keys are up to date (bin/storage upgrade).
  • Award a user a badge.
  • Try to award the same user a second badge.

That raises an error because both awards have the same recipientPHID:

Screen Shot 2016-03-25 at 10.17.11 AM.png (1×1 px, 233 KB)

To fix this:

  • Remove 'unique' => true from this key.
  • Run bin/storage upgrade.

Then the steps above should work properly.

src/applications/badges/storage/PhabricatorBadgesTransaction.php
41

The AWARD and REVOKE stories currently use generic rendering in timelines and feed -- here's timeline:

Screen Shot 2016-03-25 at 10.19.36 AM.png (136×302 px, 18 KB)

Here's feed:

Screen Shot 2016-03-25 at 10.19.03 AM.png (382×452 px, 46 KB)

These should say something like "alice awarded this badge to: bob, clara."

You can fix this by providing strings here (in getTitle()) and below (in getTitleForFeed()).

src/view/phui/PHUITimelineView.php
266

Oh, we lost this, which changed behavior a little bit: previously, we only showed active badges on timeline. Now, we'll show all badges. To reproduce this:

  • Award a user a badge.
  • View a comment they've made (you should see the badge).
  • Archive the badge (you should no longer see it).

Prior to this change, archiving a badge hid it; now it is shown. The easiest way to fix this is probably to just make sure the badge is active below, before you add it to the $badges array.

This revision now requires changes to proceed.Mar 25 2016, 5:32 PM
lpriestley edited edge metadata.
lpriestley marked 3 inline comments as done.

Don't show archived badges in timeline view, allow users to have multipls badge awards (saving transaction titles for another commit)

epriestley edited edge metadata.
epriestley added inline comments.
src/view/phui/PHUITimelineView.php
268–279

This isn't quite right, since we'll slice first, then skip archived badges. So if you have 3 badges but the first 2 are archived, the third one will be thrown away and then the two archived ones will be hidden.

But this will almost always do something reasonable in actual cases, and we can clean it up later.

This revision is now accepted and ready to land.Mar 25 2016, 11:43 PM
lpriestley edited edge metadata.

First filtering out inactive badges, then picking first two, for timeline view.

This revision was automatically updated to reflect the committed changes.