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

Remontée en base de fichier GTFS et calculs des prochains départs #2105

Merged
merged 39 commits into from
Feb 28, 2022

Conversation

fchabouis
Copy link
Contributor

@fchabouis fchabouis commented Feb 8, 2022

PR assez grosse, en deux parties.
Désolé pour la taille, mais elle a l'avantage de ne "rien faire" pour le moment, ce qui est moins stressant.
Les imports doivent pour l'instant être lancés à la main, le calcul des prochains départs est implémenté, mais pas encore utilisé.

Remontée en base de GTFS

Cette partie commence par un super stream.
Stream depuis S3 du contenu du zip
Stream de decodage du contenu CSV
stream de transformation du contenu pour se préparer à l'insertion
Stream d'insertion vers la base de données

Chaque fichier du CSV du GTFS a sa table avec des noms de colonnes qui correspondent.
Sauf pour calendar, qui a une colonne additionnelle qui permet de faciliter les requêtes par la suite.

Plusieurs GTFS vont pouvoir être importés dans les mêmes tables, car à chaque import est associé un data_import_id.
On pourra aussi importer plusieurs fois la même ressource history au besoin.

Toutes les tables du GTFS ne sont pas encore importées, il y a pour l'instant :

  • stops.txt
  • stop_times.txt
  • trips.txt
  • calendar.txt
  • calendar_dates.txt

Pourquoi celles-ci ? Car...

Calcul des prochains départs 🚂

Première utilisation de nos tables GTFS : calculer les prochains départs. C'est un premier jet, et ça a l'air de fonctionner.
C'est pour le moment une grosse requête SQL qui s'en charge, mais qui n'est pas très lisible.
Elle gère les calendriers (calendar.txt) et les exceptions (calendar_dates.txt), les trips qui commencent un jour et se termine le lendemain.

La fonction s'appelle de la manière suivante :

Transport.GtfsQuery.next_departures(stop_id, data_import_id, ~U[2022-01-17 08:00:00Z], 10)

Ce qui va sortir tous les départs pour l'import de GTFS data_import_id, du stop stop_id, ayant lieu dans les 10 minutes après le 17/1/2022 à 8h du matin.

Remarques :

  • je n'ai pas mis d'index sur les tables pour le moment, on pourra les rajouter par la suite si les requêtes s'avèrent gourmandes
  • il n'y a pas beaucoup d'info sur ce qui va effectivement passer au stop (ligne, direction, etc), ce que l'on pourra aussi rajouter par la suite.
  • il n'y a pas non plus de job qui va importer les GTFS en base, je préfère commencer tranquillement par quelques GTFS dont l'import est lancé manuellement.

@fchabouis fchabouis requested a review from a team as a code owner February 8, 2022 16:11
Copy link
Contributor

@thbar thbar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quelques notes sur le WIP:

  • Voir usage de NimbleCSV.RFC4180 ici https://github.com/etalab/transport-labs/pull/1/files
  • Il faudra "assez rapidement" faire un test de masse pour vérifier le comportement de la lib Unzip sur la totalité des fichiers (on peut avoir des surprises) -> je peux me charger de ça sans souci en asynchrone ; histoire d'éviter qu'on avance trop et que seuls X% des fichiers sont correctement traités par exemple
  • On gagnerait à dégager un "mock S3" qui travaille juste avec un répertoire en local, ou structurer le code de façon à ce que ça joue bien sans avoir à lancer un "faux S3" en local et sans cellar distant
  • Dans le futur ça sera peut-être intéressant de faire un "pré-cache local" du téléchargement S3 (notamment en dév) pour ne pas télécharger à chaque tour

Beau boulot !

apps/db/lib/db/gtfs_import.ex Outdated Show resolved Hide resolved
apps/db/lib/db/gtfs_import.ex Show resolved Hide resolved
apps/db/lib/db/gtfs_stop.ex Show resolved Hide resolved
apps/db/lib/db/gtfs_stop.ex Show resolved Hide resolved
field(:location_type, :binary)
end

def fill_stop_from_resource_history(resource_history_id) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Même en mode WIP, le code est top !

@AntoineAugusti AntoineAugusti marked this pull request as draft February 9, 2022 09:10
@thbar
Copy link
Contributor

thbar commented Feb 9, 2022

Autres éléments discutés par téléphone:

  • On voudra probablement un layer au dessus du "unzip S3" pour avoir le choix entre une implémentation qui va taper dans un bête répertoire local (et minimiser ainsi le tooling nécessaire, pas de minio ou de cellar distant etc) et une vraie implémentation s3
  • Vu comment la librairie fonctionne, support "random access", on peut tout à fait imaginer streamer directement de S3 vers le CSV puis insérer la donnée par chunks, de façon scalable (= capacité à gérer un GTFS de n'importe quelle taille sans erreur)
  • On garde l'option ouverte de faire un "cache sur le disque à la volée" si on veut qu'un fichier déjà lu depuis S3 soit en fait lu en local, avec auto-péremption
  • Il faut faire attention au fait que certains fichiers ZIP ne peuvent pas être lus en streaming, car il manque le descripteur de liste des fichiers en début de fichier ; en particulier ça empêche de streamer en HTTP de façon solide (sauf exception). Mais le protocole S3 permet de faire du "random access over HTTP" bien supporté, et donc on peut aller chercher juste ce qui nous intéresse.
  • Les librairies CSV courantes en Elixir sont https://hex.pm/packages/csv et https://hex.pm/packages/nimble_csv. La première est plus "featureful" et plus permissive, la deuxième plus optimisée, légère, et moins riche en dette technique.

@thbar thbar changed the title WIP GTFS => DB Début de remontée en base de fichier GTFS Feb 9, 2022
@fchabouis
Copy link
Contributor Author

Ah j'ai compris, il est possible de définir des Custom Types avec Ecto, ce qui revient à implémenter 4 callbacks, comme expliqué ici. Et c'est exactement ce qui est fait . Je vais essayer le fork pour voir si je peux relaxer la version de Postgrex.

@fchabouis fchabouis changed the title Début de remontée en base de fichier GTFS Remontée en base de fichier GTFS et calculs de prochains départs Feb 18, 2022
@fchabouis fchabouis marked this pull request as ready for review February 18, 2022 14:44
@fchabouis fchabouis changed the title Remontée en base de fichier GTFS et calculs de prochains départs Remontée en base de fichier GTFS et calculs des prochains départs Feb 18, 2022
Copy link
Member

@AntoineAugusti AntoineAugusti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je trouve ça très cool, bon boulot ! Le code me parait globalement être une bonne base et demande maintenant à être testé en production avec plusieurs GTFS et cas. C'est une excellente base sur laquelle construire.

apps/db/lib/db/gtfs_import.ex Show resolved Hide resolved
apps/db/lib/db/gtfs_calendar dates.ex Show resolved Hide resolved
apps/db/lib/db/data_import.ex Show resolved Hide resolved
apps/transport/lib/S3/unzip.ex Show resolved Hide resolved
apps/transport/lib/jobs/gtfs_to_db.ex Show resolved Hide resolved
apps/transport/lib/jobs/gtfs_to_db.ex Show resolved Hide resolved
apps/transport/lib/jobs/gtfs_to_db.ex Show resolved Hide resolved
apps/transport/lib/transport/gtfs_query.ex Show resolved Hide resolved
apps/transport/lib/transport/gtfs_query.ex Show resolved Hide resolved
apps/db/lib/db/data_import.ex Show resolved Hide resolved
apps/db/lib/db/gtfs_calendar dates.ex Show resolved Hide resolved
apps/db/mix.exs Show resolved Hide resolved
apps/transport/lib/transport/gtfs_query.ex Show resolved Hide resolved
Copy link
Contributor

@thbar thbar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quelques petites remarques, mais c'est mineur (nommage etc).

On pourra se faire un exercice de "mise en place de spécs" dans une prochaine PR, d'autant plus que le GTFS-RT après sera utilisé pour corriger la timetable.

Une approche pourrait être de publier notre propre "testing set", voire, de le mutualiser avec MobilityData, ou de nous appuyer sur un outil existant solide pour comparer l'interprétation.

Il y a un conflit à régler !

Superbe boulot !!!

@fchabouis fchabouis enabled auto-merge (squash) February 28, 2022 16:07
@fchabouis fchabouis merged commit 5e0b724 into master Feb 28, 2022
@fchabouis fchabouis deleted the gtfs_to_database branch February 28, 2022 16:10
This was referenced Mar 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants