Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cars] locations/signals : Comment gérer la pagination ? #47

Open
josephpage opened this issue Sep 28, 2016 · 6 comments
Open

[Cars] locations/signals : Comment gérer la pagination ? #47

josephpage opened this issue Sep 28, 2016 · 6 comments

Comments

@josephpage
Copy link
Contributor

Sur les endpoints /cars/{id}/locations et /cars/{id}/signals on peut ajouter un paramètre limit,
ce qui permet de faire à peu près le même effet que de la pagination,
mais dans le résultat que retourne l'API on ne voit pas si ce paramètre a eu un effet... ou pas.

On ne peut donc pas savoir si il est nécessaire de faire une requête supplémentaire pour avoir toutes les datas sur la période de temps initialement demandée.

A minima, un header HTTP serait utile pour donner le nombre total de résultats :
Xee-Limit-Total-Results: 350000 (350 000 est un cas réel sur un de nos véhicules)

Idéalement, vous pourriez fournir un header Link pour donner l'url de la page suivante (best practice des API REST), en conservant les paramètres de la requête initiale. Il suffirait juste de modifier le paramètre end pour qu'ils ne sélectionnent pas les locations déjà retournés :

Link: <https://cloud.xee.com/api/v3/cars/{carId}/locations
   ?begin={begin de la requête initiale}
   &end={date de la plus ancienne location parmi les résultats, ou n+1 pour l'exclure}
   &limit={limit de la requête initiale}>; rel="next"

Avez-vous d'autres solutions en tête ?
Comment faire en attendant ?

@qk7b
Copy link
Contributor

qk7b commented Oct 8, 2016

Bonjour Joseph,

Sur nos APIs le paramètre limite est plutôt là pour éviter une surcharge que pour gérer la pagination.
Nous n'étions pas certains de le garder à la base.

Aujourd'hui, nous pensons qu'une pagination de date à date permet de rentre l'API plus intuitive dans bon nombre de cas. Cette limite sert par exemple à obtenir les 10 dernières positions GPS connues.

En revanche l'idée d'un Header pour indiquer le nombre total de résultats a du sens. Nous prenons note.

@josephpage
Copy link
Contributor Author

Une pagination date à date est effectivement très intuitive... ou pas.

Le propre d'une pagination c'est d'avoir des packets de données limités et constants.
x données par x données, jusqu'à la dernière page où on obtient x ou moins.

Avec le fonctionnement actuel on a 2 techniques possibles :

  1. faire une requête x(1) avec une limite y, puis refaire la même requête x(2) avec la même limite y mais avec un begin correspond à la date du dernier signal de la requête x(1)
  2. trouver l'interval de temps minimal pour lequel on obtient le nombre maximal de valeurs qu'on souhaite. Dans notre cas, on a trouvé qu'en faisant les requêtes jour par jour, notre backend arrive à s'en sortir

Problèmes :

  1. a. on rate systématiquement les signaux qui ont le même timestamp que la dernière valeur de la requête précédente, ou il faut mettre en place un contrôle de déduplication de données (très couteux vu le nombre de données)
  2. b il faut penser à gérer le chevauchement des mois...
  3. on peut avoir y signaux ou 0 signaux, c'est imprévisible, et pire, on ne peut pas connaître la fin avant d'avoir tout essayé, puisque l'absence de signaux ne signifie pas la fin des résultats

En tout cas très intéressé pour une astuce à ce sujet ;)

@denouche
Copy link
Contributor

Juste pour apporter quelques éléments:
On peut utiliser des headers HTTP standards plutôt que d'en inventer d'autres pour la pagination.
Le header Range permet dans une request de demander seulement une partie de la ressource, et en réponse on peut imaginer un status HTTP 206 (Partial content), et un header content-range.

@qk7b
Copy link
Contributor

qk7b commented Oct 25, 2016

Pour le coup, j'ai du mal à saisir le problème.

Si la requête jour/jour est faite a 23:59:59:999 les chances de "rater" des signaux de la journée qui vient de passer sont vraiment proches de 0 non ?

@josephpage
Copy link
Contributor Author

@denouche Le HTTP 206 est surtout utilisé pour le streaming de fichier lourds (images/vidéos/zip/tar) pour lesquels on veut que le téléchargement soit résistant aux interruptions. Le header Link est un standard (RFC-5988). L'API Github est souvent nommée comme une des meilleurs implémentations de pagination.

@quentin7b En effet avec une requête jour/jour faite a 23:59:59:999 on a très très peu de chance de rater des signaux.

Cas d'usage où une pagination basique est essentielle :

Je veux faire l'analyse d'un véhicule sur les données des 2 dernières années.
Disons que pour les 2 ans, cela représente 1 million de lignes de données (locations+signals) soit 42 000 lignes/mois
malheureusement la capacité de buffering de mon serveur n'est que de 10000 lignes

  • si je fais des requêtes par mois, je risque de dépasser ma capacité de buffering
  • si je fais des requêtes par semaine, pareil
  • si je fais des requêtes par journée, je risque de faire beaucoup de requêtes pour rien si le véhicule n'a pas roulé, ou peut-être dépasser ma capacité de buffering si le véhicule a beaucoup roulé
  • si je fais des requêtes par heure, pas de soucis en vue mais ... 24x365x2 = 17520 ... OMG!

L'impossibilité de prédire la taille de la réponse est problématique.

@josephpage
Copy link
Contributor Author

josephpage commented Feb 22, 2017

Une autre solution pour faciliter le traitement des résultats locations/signals seraient de retourner les données dans un format CSV. Si 1 ligne = 1 donnée, il très facile de garder l'ensemble du résultat sous une forme peu consommatrice en mémoire, et d'itérer à son rythme sur toutes les lignes.

Pour les locations :

{timestamp},{latitude},{longitude},{altitude},{satellites},{heading}

exemple :

1456799060000,50.67815,3.208155,31.8,4,167

Pour les signals :

{timestamp},{name},{value}

exemple :

1456799060000,LockSts,0

Putting the timestamp first allows quick filter/sort/inverse by date, before parsing ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants