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

API Diff : passer la réponse en streaming #462

Merged
merged 9 commits into from
Sep 26, 2024
Merged

Conversation

fchabouis
Copy link
Collaborator

@fchabouis fchabouis commented Sep 18, 2024

Dans cette PR, j'utilise la fonction StreamingHttpResponse fournie par Django qui permet de renvoyer une réponse HTTP dont le contenu est généré au fur et à mesure de l'envoi, par opposition à HttpResponse qui prend en argument un contenu qui doit déja être généré au moment où l'envoi commence.

La fonction copy_expert de psycopg2 permet également de streamer du contenu depuis la base de donnée vers le code Python.

La difficultée rencontrée a été de mettre ces 2 streams "bout à bout", c'est à dire que le résultat de copy_expert soit passé au fur et à mesure à StreamingHttpResponse, sans que l’entièreté de la donnée de soit stockée à aucun moment par le code python.

La seule manière de faire que j'ai trouvée jusqu'à présent a été de forker le processus, que le processus child fasse la requête Postgres et stream le résultat sur un pipe qui peut être lu au fur et à mesure par le processus parent qui en envoie le contenu à StreamingHttpResponse.

J'aurais préféré que tout soit fait par le même processus, pour ne pas créer de process au niveau de l'OS pour répondre à une requête GET sur le site, parce qu'on ne peut créer qu'un nombre limité de process sur le serveur avant d'avoir des problèmes.

On peut quand même merger la fonctionnalité, quitte à revenir et l'améliorer par la suite si on voit que créer un thread pour l'occasion pose problème.

J'ai fait un test en local sur un diff massif. Avant la PR, la requête HTTP restait en attente de réponse pendant 8minutes, puis se mettait à télécharger le diff à toute vitesse (toute la donnée est donc générée sur le serveur avant de commencer à être envoyée), risque de timeout important et de crash du serveur si toute la ram est utilisée. Avec le streaming, la réponse met seulement quelques secondes à démarrer, puis se télécharge à un rythme bien plus lent, qui est en fait la vitesse à laquelle la base de donnée arrive à sortir ses résultats. La durée totale de l'opération est sensiblement la même.

j'ai posé une question ici aussi, pas eu de réponse pour le moment.

@fchabouis fchabouis marked this pull request as ready for review September 23, 2024 14:22
@fchabouis fchabouis changed the title WIP diff stream API Diff : passer la réponse en streaming Sep 24, 2024
Copy link
Contributor

@pauletienney pauletienney left a comment

Choose a reason for hiding this comment

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

LGTM. J'ai simplement ajouté en commentaire une proposition de solution alternative si cette recette venait à poser problème.

app/api_alpha/views.py Show resolved Hide resolved
Copy link
Contributor

@pauletienney pauletienney left a comment

Choose a reason for hiding this comment

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

Go

@fchabouis fchabouis merged commit 60b0071 into main Sep 26, 2024
5 checks passed
@fchabouis fchabouis deleted the stream_http_response branch September 26, 2024 14:25
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.

2 participants