Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Multiprocessing ou Threading

0 votes

Avec Django, j'ai produit une "management command" (lanceée depuis une crontab toutes les 15min) qui récupère des triggers (depuis une model), et, via multiprocessing, déclenche (en rafale de 5 par 5) une fonction qui traite ces triggers.

Les triggers sont reliés à des services (genre Pocket, Evernote, Readability, etc) possedant un token, c'est en fournissant se token à l'API de ces services qu'on peut créer les info adequates.

Tout ceci fonctionnait très bien jusqu'à ce que j'ajoute un service (Wallabag) dont la durée de vie du token est plus courte (1heure contre un an avec les autres services)

Donc je suis parti pour gérer l'erreur 401 et quand je la rencontre je rafraichis le token. Token que je stocke aussitôt dans la base pour la prochaine "utilisation" pour que le trigger utilisant ce même service, puisse à son tour en bénéficier.

Tout ça marche, mais le truc qui me dérange, c'est que si j'ai 5 triggers pour wallabag, je vais mettre 5 fois à jour le token du service car les triggers (avec le token expiré du coup) sont tous récupérés avant de déclencer le multiprocessing.

Ce n'est donc qu'à la prochaine execution de la "management commande" que le token ne sera plus remis à jour (en fait 3 fois par heure puisque executer tous les 15min).

Question : du coup vaut il mieux utiliser Thread ? ou y a t-til un autre moyen d'éviter de mettre à jour le model 'n' fois pour rien pour que les autres process récuperent le bon token ?

demandé 4-Mai-2016 par foxmask (2,830 points)

2 Réponses

0 votes

La solution est de ne pas renouveler le token au niveau de la requête. Fait un autre service dont le pub est de pinger les APIs tous les x temps (un poil plus court que ton cron), et renouveler les tokens. Puis envoie les tokens à test workers soit via une file, soit via un message WAMP, soit si le service est cronifié et fait du one shot, dans un fichier de config.

D'une manière générale, c'est une bonne pratique d'avoir un service à part qui gère la configuration de tes workers, car ça te permet de découpler le travail et la configuration.

répondu 4-Mai-2016 par Sam (4,974 points)

Je m'attendais bien comme réponse à un service qui ne fasse que renouveler les tokens.

Chez IFTTT, par exemple, il détecte qu'un service ne repond plus correctement, et au bout de 'n' tentatives d'utilisation de l'api cible infructueuses, il désactive le service et mail au user.

Du coup je me demandais si c'était le role de l'application de se substituer à l'utilisateur qui devrait lui même appuyer sur le bouton de renouvellement du token dans l'application.

C'est pour ça que j'étais parti dans cette direction. (détecter une 401 et renouveler le token dans la base).

Sinon in fine le process de IFTTT me plait bien et j'avais pour plan de m'en inspirer pour TriggerHappy.

0 votes

Il ne serait pas possible de placer le token dans un objet partagé?
https://docs.python.org/3.5/library/multiprocessing.html#multiprocessing.Value

Un objet multiprocessing.Value pourrait contenir ton token. Il inclue un système de lock évitant que tes trigger se marchent sur les pieds et le premier qui rencontre la 401 met à jour le token qui sera utilisable pour tes autres triggers.

répondu 4-Mai-2016 par Poisson (272 points)

ma commande est là.

Pour acceder au token (issue du QuerySet) je dois itérerer sur trigger dès lors il est accessible via :

for service in trigger:
     print(service.consumer.token)

Est-ce possible dans ce cas de figure d'exploiter multiprocessing.Value ?

si je comprends l'interet de multiprocessing.Value c'est qu'une fois Value appelée, son contenu ne varie plus d'un iota ?

Mais ca serait génant dans mon cas (si c'est bien comme cela que ca fonctionne) parce que :

au premier 401 je mets un nouveau token dans Value(), au second 401 je recupere le token venant de Value() ; ca ok ca me plait
au cas où pour le meme service mais pour un autre user, je rencontre une 401, je peux écraser le token de Value() ou c'est trop tard ?
Parce que pour 2 users les tokens sont bien evidement pas les mêmes.

Ensuite si je pousse le bouchon plus loin :

Value() est peuplé d'un token pour le service Wallabag, mais si ensuite j'ai aussi un token expiré pour Twitter et rencontre une 401, je vais aussi recuperer le token de Wallabag qui ne va pas coller, non ?

Value est une variable partagé entre tes différents processus. Donc si tu changes cette valeur dans un process, tu vas le changer dans tous les process. Elle n'est pas figé du tout, mais partagé et protégé par un lock (pour éviter que deux process en modifie la valeur en même temps).

Tu vas sans doute avoir besoin d'éléments plus complexe, et le module Multiprocessing fourni un objet Manager() qui permet de partager des objets python entre process, y compris des dictionnaire.

Du coup pourquoi pas un dico partagé contenant les différents token pour les usagers?

Mais je pense que les techno web ont des outils plus adaptés (je suis plutôt originaire du calcul scientifique, les problématiques sont pas tout à fait les même).

Je suppose que l'inscription dans un fichier de config, ou alors une mini bdd/autre pourrait faire le boulot aussi (ce sont des méthodes permettant également de transmettre des info entre processus).

Merci pour ces précisions

...