Page MenuHomePhabricator

Implement proper limit and pagination for organizer lists
Closed, ResolvedPublic

Description

OrganizersStore::getEventOrganizers() currently supports a limit parameter, and will also need to support basic pagination for T316137. However, I just realized that the existing logic is broken: the query is something like

SELECT ceo_user_id, ceo_role_id FROM ce_organizers WHERE ceo_event_id = 42 AND ceo_deleted_at IS NULL LIMIT 50

but this doesn't work because each user can have multiple rows, one for each role, so the limit could potentially truncate the result set, and only include a partial list of roles for a user.

Additionally, implementing pagination is not that easy, because the only unique key that we could use is ceo_id, but that cannot be easily represented in the code, because ceo_id identifies a user+event+role combination, not a user+event combination, and so it can't be unambiguously be stored inside a Organizer object.

Acceptance criteria

  • Pagination is implemented in the backend
  • The "List the organizers of an event" accepts a parameter for the last organizer ID and the parameter, as well as the response, are documented

Event Timeline

I think a possible approach would be to have getEventOrganizers() return a "continuation token" (in practice, the ceo_id of the last row in the result set), and callers could pass it as well. Maybe it could be a pass-by-ref parameter.

I think a possible approach would be to have getEventOrganizers() return a "continuation token" (in practice, the ceo_id of the last row in the result set), and callers could pass it as well. Maybe it could be a pass-by-ref parameter.

That works, we'd have to be explicit about ordering of course.

I think a possible approach would be to have getEventOrganizers() return a "continuation token" (in practice, the ceo_id of the last row in the result set), and callers could pass it as well. Maybe it could be a pass-by-ref parameter.

That works, we'd have to be explicit about ordering of course.

Indeed, and I already noticed that we're currently relying on implicit ordering in a few places, which I'm going to fix in a separate patch.

Decision: count and limit will be fixed as part of T318379. This task remains about implementing pagination.

Change 834556 had a related patch set uploaded (by Daimona Eaytoy; author: Daimona Eaytoy):

[mediawiki/extensions/CampaignEvents@master] Change storage of organizer roles

https://gerrit.wikimedia.org/r/834556

Change 834562 had a related patch set uploaded (by Daimona Eaytoy; author: Daimona Eaytoy):

[mediawiki/extensions/CampaignEvents@master] Implement basic pagination for organizer lists

https://gerrit.wikimedia.org/r/834562

Change 834556 merged by jenkins-bot:

[mediawiki/extensions/CampaignEvents@master] Change storage of organizer roles

https://gerrit.wikimedia.org/r/834556

Change 834562 merged by jenkins-bot:

[mediawiki/extensions/CampaignEvents@master] Implement basic pagination for organizer lists

https://gerrit.wikimedia.org/r/834562

Daimona removed a project: Patch-For-Review.
Daimona added a subscriber: vaughnwalters.

@vaughnwalters Quick note for QA: the pagination should be testable through the "list organizers of an event" endpoint, by providing the last_organizer_id parameter (that you can grab from the organizer_id field in the response).

@Daimona I think the organizer_id that is coming back from the list organizers of an event endpoint may be incorrect. It always returns the event ID, not the organizer ID. So when I put the that ID into a query string with last_organizer_id it brings back an empty array. Check out the gif below and let me know if I am just missing something here. Also the doc for that endpoint says it should be returning participant_id but using that endpoint without a query param, the API returns organizer_id.

Screen Recording 2022-09-29 at 1.37.36 PM.gif (1×2 px, 2 MB)

@Daimona I think the organizer_id that is coming back from the list organizers of an event endpoint may be incorrect. It always returns the event ID, not the organizer ID.

I think this is simply a consequence of the event ID and the organizer ID being auto_increment values, and the fact that every event has exactly one organizer, so the two IDs would be the same. In short, a coincidence.

So when I put the that ID into a query string with last_organizer_id it brings back an empty array.

If each event only has a single organizer, this is expected. "last_organizer_id" is the last organizer on the previous batch, so if there's a single organizer, there's nobody to show after them. All in all, unless I'm missing something I think this is working as intended.

Also the doc for that endpoint says it should be returning participant_id but using that endpoint without a query param, the API returns organizer_id.

Right, copypasta fixed.

@Daimona I think the organizer_id that is coming back from the list organizers of an event endpoint may be incorrect. It always returns the event ID, not the organizer ID.

I think this is simply a consequence of the event ID and the organizer ID being auto_increment values, and the fact that every event has exactly one organizer, so the two IDs would be the same. In short, a coincidence.

Ah, okay right that makes sense.

So when I put the that ID into a query string with last_organizer_id it brings back an empty array.

If each event only has a single organizer, this is expected. "last_organizer_id" is the last organizer on the previous batch, so if there's a single organizer, there's nobody to show after them. All in all, unless I'm missing something I think this is working as intended.

for this query param, if I put in any integer, it still returns the empty array. I think this is okay, but just checking to make sure @Daimona. for example, /campaignevents/v0/event_registration/1/organizers?last_organizer_id=23423412412 will bring back an empty array just the same as the correct last_organizer_id would.

for this query param, if I put in any integer, it still returns the empty array. I think this is okay, but just checking to make sure @Daimona. for example, /campaignevents/v0/event_registration/1/organizers?last_organizer_id=23423412412 will bring back an empty array just the same as the correct last_organizer_id would.

In your example, that's because that event has no organizer with an ID larger than 23423412412, so I think it's working as intended. The endpoint does not actually check that there's an organizer with the ID specified, it only verifies whether there's any organizer with a larger ID.