Paginazione API Non-discovery

Recentemente ho lavorato con l’API groups e ho alcune riflessioni sulla paginazione, in particolare nel contesto non di discovery.

Il contesto

Per chiarezza, con “contesto di discovery” intendo la paginazione in list_controller.rb e tags_controller.rb, che utilizzano metodi simili construct_url_with per generare gli URL delle pagine precedente e successiva.

A questo proposito, questi metodi construct_url_with potrebbero essere eventualmente combinati in un modulo incluso, dato che sono abbastanza simili; tuttavia, questa paginazione è così integrale alla generazione dell’elenco dei topic da meritare una categoria separata.

Il pattern

Nel contesto non di discovery, la paginazione utilizza una versione di quanto segue:

page = params[:page].to_i
page_size = 38
items = items.offset(page * page_size).limit(page_size)

Potete vedere una variante di questo pattern in diversi controller, ad esempio (non esaustivo):

  • groups
  • web hooks
  • emails
  • notifications
  • directory items
  • staff action logs

Esistono alcuni problemi con la paginazione quando si utilizzano questi endpoint da un client di terze parti.

I problemi

Specifico: inclusione dell’URL “load more”

Alcuni di questi endpoint restituiscono un URL “load more” (con la pagina “successiva”), anche se non ci sono altre pagine.

Ad esempio, su meta sono visibili 9 gruppi (per me). Tuttavia, nella risposta JSON di quella pagina viene restituita una voce load_more_groups con una seconda pagina inesistente (la pagina “1” è la seconda pagina, poiché la numerazione delle pagine inizia effettivamente da 0):

https://meta.discourse.org/g.json

...
"total_rows_groups":9,
"load_more_groups":"/groups?page=1"

Questo potrebbe essere descritto come un “bug” dell’endpoint, poiché un client API tende spesso a utilizzare l’URL “load more” durante l’iterazione sulle pagine, invece di gestire autonomamente il conteggio delle pagine.

Generale: nomenclatura diversa, gestione della dimensione della pagina e dati di paginazione restituiti

Più in generale, nei contesti non di discovery c’è una notevole variabilità nella nomenclatura della paginazione, nelle dimensioni delle pagine e nei dati di paginazione restituiti. Ad esempio:

  • “page” è chiamato sia :page che :offset.
  • “numero totale di elementi” è talvolta incluso come total_rows_*, ma non sempre è presente e a volte è denominato diversamente.
  • la maggior parte delle dimensioni delle pagine è assegnata a variabili localmente nelle rispettive azioni e varia leggermente, il che significa che bisogna cercarle attentamente.

Suggerimento

Ora, ci sono varie ragioni per molte delle cose che ho sollevato. Molti endpoint non di discovery sono consumati principalmente (o esclusivamente) dal client dell’app Discourse e sono ottimizzati per quel client. Questo ha senso.

Detto questo, potrebbe esserci una spinta a iniziare a spostare gradualmente la paginazione non di discovery, in particolare per gli endpoint spesso consumati da client esterni (come groups), verso una maggiore standardizzazione, il che renderebbe anche più semplice risolvere problemi come l’inclusione dell’URL “load more”.

Essenzialmente, ho in mente un modulo “Pagination” che codifichi il pattern e possa gestire la paginazione in alcuni endpoint selezionati, forse iniziando con Groups.

Potrei eventualmente creare una PR a riguardo, ma ho pensato di proporla prima per discussione.

5 Mi Piace