merci olivier pour ta solution mais je préfère partir sur celle de florian; désolé de te décevoir, mais j'ai plus d'un an et demi d'expérience en RubyOnRails (tu dois me trouver vraiment nul au travers de mon code...) et application web; de plus ma solution est professionnelle et sensible; donc je préfère partir sur qq chose de plus complexe à mettre en oeuvre mais de plus costaud
Merci encore ZinburuDebain Le vendredi 2 septembre 2016 22:31:06 UTC+2, Olivier El Mekki a écrit : > > Nous parlons à quelqu'un qui débute manifestement, et il n'a pas été fait > mention que l'application serait publique. Sous réserve de confirmation par > Ziburudebian, j'ai l'impression qu'il essaie de se bidouiller un outil > d'administration à usage personnel, voir local. Dans tous les cas, débuter > rails et devoir commencer par sidekiq, action_cable, une configuration de > redis, etc est un tue-l'amour pour les débutants. Clairement, nous ne > ferions pas de la gestion de process à l'arrache comme ça dans des > applications at scale destinées au public. Mais est-ce bien la question ici? > > Tu as raison cependant, ça ne ferait pas de mal de faire un check de > l'existence d'un process en cours. Étant donné qu'il y a un pidfile, c'est > assez simple ça faire: > > ``` > def start > raise "Process is already running" if File.exists? "./app.pid" > process = spawn( "ruby ./app.rb" ) # tu lances ton process > Process.detach( process ) # tu le détaches de ton process web > end > ``` > > En cas de coupure brutale du système, il suffit de supprimer le pidfile > (c'est assez courant avec les architectures à base de lockfile). > > Cette solution, aussi peu élégante soit elle, à l'avantage d'être > abordable pour un débutant qui essaie d'accomplir quelque chose à son > usage. Les architectures plus complexes viendront avec l'envie et > l'expérience. > > Ziburudebian, à bon entendeur : tu peux faire quelque chose aussi simple à > ton usage personnel pour débuter, mais c'est un peu plus complexe que ça si > tu veux faire une application business / publique :) > > > On Friday, September 2, 2016 at 8:27:21 PM UTC+2, Florian Dutey wrote: >> >> Je pense tres honnetement que ce procede est mauvais. Tu controlles pas >> qui lance (et combien) de process. C'est un coup a te retrouver avec plein >> de process orphelins et a obtenir un deni de service de la part de ton OS. >> >> Le cas d'utilisation est plutot simple ici. T'as une base de donnees qui >> est updatee regulierement. >> Dans ce cas la, tu as 2 options tres simples: >> >> 1) Tu fais du polling. Toutes les 10 minutes, ton frontend (javascript) >> fait une requete (ajax) au backend (rails) pour recuperer le nouveau data. >> 2) tu utilises des websockets (action cable avec rails 5). C'est le >> serveur qui va pousser les donnees vers le client chaque fois qu'il y en a >> des nouvelles. Donc ca evite de faire des requetes en boucle vers le >> serveur. >> >> Quand au boutton start stop, dans le premier cas, start demarre le cycle >> de requetes ajax toutes les 10 minutes (avec setTimeout en vanilla JS). Et >> le boutton stop detruit cette boucle (clearTimeout en vanilla JS). >> >> Dans le second cas, les bouttons start et stop mettent juste a jour un >> boolean dans les etats de ta vue. Boolean qui sera evalue pour savoir si tu >> dois ignorer ou non les evenements qui sont pousses par le serveur. >> >> Pas besoin de jobs, pas besoin de daemon, pas besoin de boucle infinie >> cote serveur dans ce cas la. C'est un cas tres classique d'affichage de >> data "en temps reel". >> >> 2016-09-02 18:14 GMT+08:00 Olivier El Mekki <oelm...@gmail.com>: >> >>> Hello, >>> >>> Dans le cas que tu décris, je partirais sur quelque chose de plus simple >>> que d'utiliser daemon (qui n'est probablement pas pensé pour être utilisé >>> avec rails): lancer ton app en commande shell, lui faire stocker son pid >>> dans un pidfile, puis faire un kill sur le contenu de ce fichier. Voici un >>> example: >>> >>> La partie web: >>> >>> ``` >>> # Ce fichier est en plain ruby, mais l'idée est de reproduire le contenu >>> # des methodes #start et #stop dans tes controllers >>> def start >>> process = spawn( "ruby ./app.rb" ) # tu lances ton process >>> Process.detach( process ) # tu le détaches de ton process web >>> end >>> >>> def stop >>> %x(kill $(cat ./app.pid)) if File.exists? "./app.pid" # tu killes ton >>> process, s'il n'est pas déjà mort >>> end >>> >>> puts "starting" >>> start >>> sleep 5 >>> puts "stopping" >>> stop >>> ``` >>> >>> Dans ton cas, tu voudras probablement utiliser des path absolus plutôt >>> que relatifs. >>> >>> La partie system: >>> >>> ``` >>> # tu stock le pid de ton process >>> File.open( "./app.pid", "w" ){ |f| f.puts Process.pid } >>> >>> # tu t'assures de supprimer le pidfile quand ton process meurt >>> Kernel.at_exit do >>> File.unlink( "./app.pid" ) >>> end >>> >>> >>> # Code >>> >>> sleep 50 # juste pour executer cet example, tu n'en as pas besoin dans >>> ton code >>> ``` >>> >>> >>> >>> On Friday, September 2, 2016 at 11:35:14 AM UTC+2, ziburudebian wrote: >>>> >>>> Merci florian pour tes explications, c'est vrai que fournir du code >>>> ainsi peut paraître complexe, mais au bout d'un moment tout seul dans mon >>>> coin à coder, je craque... >>>> tu as raison, j'aurai du commencer par expliquer ce que je veux faire : >>>> >>>> sur mon formulaire j'ai 2 boutons START et STOP comme tu l'as compris >>>> dans mon code; >>>> le but lorsque je clique sur START est de lancer un programme qui à >>>> partir d'options choisies sur ma page web, analyse les données dans la >>>> base >>>> et affiche le résultat sur ma page web et le STOP arrête cette analyse; >>>> les données (que j'analyse) qui alimente ma base sont mises à jour par >>>> un programme externe toutes les 10 minutes, c'est pour cela que j'ai pensé >>>> à un boucle infinie qui démarre sur le bouton START >>>> >>>> >>>> Le jeudi 1 septembre 2016 19:14:26 UTC+2, Florian Dutey a écrit : >>>>> >>>>> Si tu veux utiliser daemon et rails en meme temps, il faut que tu >>>>> ecrives dans une queue intermediaire (par exemple redis). Le daemon >>>>> monitor >>>>> la queue (boucle infinie), quand ya des nouveaux messages dedans, il les >>>>> depiles et les traite. Ton controller ne doit jamais inclure la gem >>>>> daemon >>>>> et tu ne dois jamais appeler des scrips depuis ton controller, sinon la >>>>> gem >>>>> daemon ne sert a rien en fait, tu peux appeler le script directement avec >>>>> system() et c'est degueulasse. >>>>> >>>>> Quand a ton probleme courant, ce qu'on voit dans ton exemple, c'est >>>>> que tu passes tes ids client en mode "1-2-3-4" depuis le controller et en >>>>> mode "1 2 3" depuis le shell. >>>>> >>>>> Quand au script lui meme, pourquoi lui filer une loop alors que ca >>>>> sert a rien? C'est pas daemon, c'est un script shell ca >>>>> C'est aussi plus clean de faire un truc genre >>>>> Client.find(*client_ids).each { } plutot que client_ids.each { |id| c = >>>>> Client.find(id) #... } Dans un cas t'as un seul call SQL et dans l'autre, >>>>> t'as autant de calls que d'ids. >>>>> >>>>> Le code de ton daemon est tres confus. On ne demarre pas un daemon >>>>> depuis un controller. Le daemon doit tourner tout le temps et recevoir >>>>> des >>>>> signaux. La tu ne controlles pas combien de daemon seront demarres en >>>>> parallele. Il suffit de spammer ton serveur pour demarrer des tonnes de >>>>> daemon et faire peter l'OS qui sera perdu dans les millions de process >>>>> crees par le serveur. Le fait de stopper quand ton utilisateur veut bien >>>>> penser a cliquer sur stop (ce qu'il ne fera jamais) me permet de te >>>>> predire >>>>> que tu vas devoir redemarrer tes serveurs souvent, et que ton app ne >>>>> serait >>>>> jamais disponible. >>>>> >>>>> En fait, si tu decrivais ce que tu cherches reellement a faire, ca >>>>> permettrait probablement de t'aiguiller un peu mieux. Mais la, le code, >>>>> y'a >>>>> tellement de fondamentaux qui manquent que personne peut prendre le temps >>>>> de te donner la solution. >>>>> >>>>> 2016-09-01 17:52 GMT+08:00 Philippe Creux <pcr...@gmail.com>: >>>>> >>>>>> Bonjour, >>>>>> >>>>>> Rails et daemon ne doivent pas faire bon ménage. >>>>>> >>>>>> Pour faire tourner des tâches de manière asynchrone dans une >>>>>> application Ruby on Rails, je te conseille d'utiliser ActiveJob ( >>>>>> http://guides.rubyonrails.org/active_job_basics.html) et Sidekiq. >>>>>> >>>>>> Bon courage! >>>>>> >>>>>> -- >>>>>> φ <http://pcreux.com> >>>>>> >>>>>> >>>>>> 2016-08-31 16:06 GMT+02:00 ziburudebian <devm...@gmail.com>: >>>>>> >>>>>>> Bonjour à tous >>>>>>> >>>>>>> J'utilise la gem *daemon *mais mon programme ne lit pas toutes les >>>>>>> données de ma table client : il y a 5 enregistrements, il s'arrête au >>>>>>> deuxième !!! ça fait trois jours que je cherche, j'en peux plus .... >>>>>>> Voici mon code : >>>>>>> >>>>>>> *runexecution *est la fonction que je lance depuis le bouton de mon >>>>>>> formulaire; elle est décrite dans >>>>>>> *app/controllers/executions_controller.rb* >>>>>>> >>>>>>> class ExecutionsController < ApplicationController >>>>>>> >>>>>>> def runexecution >>>>>>> # >>>>>>> ============================================================================================================ >>>>>>> # DESCRIPTION : Permet de demarrer ou arreter l'execution d'un >>>>>>> script (action=start ou stop) >>>>>>> # >>>>>>> ============================================================================================================ >>>>>>> require 'daemons' >>>>>>> # ---------------------------- >>>>>>> # traitement des parametres >>>>>>> # ---------------------------- >>>>>>> return "" if params.nil? # ce test permet de ne pas rentrer >>>>>>> dans la fonction lors de l'appel via le menu >>>>>>> action = "" >>>>>>> params.each do |key,value| >>>>>>> action = "start" if (key.index("loopstart") != nil) >>>>>>> action = "stop" if (key.index("loopstop") != nil) >>>>>>> end >>>>>>> logger.info("******************action="+action) >>>>>>> case action >>>>>>> when "start" >>>>>>> exedate = "2015-10-03 08:30" >>>>>>> frequence = "0.05" >>>>>>> listclientselectionne = "1-2-3-4-5" >>>>>>> paramopt = "" >>>>>>> options = {:ARGV => [action, paramopt, '--', exedate, >>>>>>> frequence, listclientselectionne], >>>>>>> :dir_mode => :script, >>>>>>> :dir => 'tmp/pids', >>>>>>> :multiple => true, >>>>>>> :ontop => true, >>>>>>> :mode => :load, >>>>>>> :backtrace => true, >>>>>>> :monitor => true, >>>>>>> :log_output => true >>>>>>> } >>>>>>> logger.info("******************options="+options.to_s) >>>>>>> Daemons.run('myserver.rb', options) >>>>>>> logger.info("******************FIN") >>>>>>> >>>>>>> when "stop" >>>>>>> logger.info("******************loopstop") >>>>>>> else >>>>>>> redirect_to executions_execution_path >>>>>>> end # case action >>>>>>> >>>>>>> end # runexecution >>>>>>> >>>>>>> end #class >>>>>>> >>>>>>> le programme qui tourne en boucle est* myserver.rb* qui est à la >>>>>>> racine de mon site : >>>>>>> >>>>>>> #!/usr/bin/env ruby >>>>>>> ENV['RAILS_ENV'] ||= 'production' >>>>>>> require File.expand_path('../config/environment', __FILE__) >>>>>>> print "\nParametres= " + ARGV[0].to_s + "****" + ARGV[1] + "****" + >>>>>>> ARGV[2] + "\n" >>>>>>> exedate = ARGV[0] >>>>>>> frequence = ARGV[1] >>>>>>> listclientselectionne = ARGV[2] >>>>>>> delai = frequence.to_f * 60 >>>>>>> listclientselectionne = listclientselectionne.split("-") >>>>>>> print "Nbclient=" + listclientselectionne.count.to_s + "\n" >>>>>>> loop do >>>>>>> print Time.now.to_s + "\n" >>>>>>> listclientselectionne.each do |idcl| >>>>>>> print idcl + "\n" >>>>>>> begin >>>>>>> print "avant\n" >>>>>>> objclient = Client.find(idcl) >>>>>>> print "apres\n" >>>>>>> if (!objclient.nil?) >>>>>>> print objclient.lastname.to_s + "\n" >>>>>>> # print objclient.name + "\n" >>>>>>> else >>>>>>> print "Erreur sur " + idcl + "\n" >>>>>>> end >>>>>>> rescue ActiveRecord::RecordNotFound => e >>>>>>> objclient = nil >>>>>>> print "Erreur \n" >>>>>>> end >>>>>>> end >>>>>>> sleep(delai) >>>>>>> end >>>>>>> >>>>>>> et voici les résultat à 'écran >>>>>>> >>>>>>> => Booting Thin >>>>>>> => Rails 4.1.7 application starting in production on >>>>>>> http://0.0.0.0:3000 >>>>>>> => Run `rails server -h` for more startup options >>>>>>> => Notice: server is listening on all interfaces (0.0.0.0). Consider >>>>>>> using 127.0.0.1 (--binding option) >>>>>>> => Ctrl-C to shutdown server >>>>>>> Thin web server (v1.6.4 codename Gob Bluth) >>>>>>> Maximum connections set to 1024 >>>>>>> Listening on 0.0.0.0:3000, CTRL+C to stop >>>>>>> myserver.rb: process with pid 28318 started. >>>>>>> >>>>>>> Parametres= 2015-10-03 08:30****0.05****5-1-6-2 >>>>>>> Nbclient=5 >>>>>>> 2016-08-31 15:47:56 +0200 >>>>>>> 1 >>>>>>> avant >>>>>>> apres >>>>>>> DURANTON >>>>>>> 2 >>>>>>> avant >>>>>>> apres >>>>>>> VALENT >>>>>>> 3 >>>>>>> avant >>>>>>> log writing failed. closed stream >>>>>>> log writing failed. closed stream >>>>>>> log writing failed. closed stream >>>>>>> >>>>>>> >>>>>>> Si j'exécute le programme *myserver.rb* depuis la console avec *ruby >>>>>>> myserver.rb 1 2 3 : *tout se passe bien; voici le stdout >>>>>>> >>>>>>> # ruby myserver.rb 1 2 3 >>>>>>> Parametres= 1****2****3 >>>>>>> Nbclient=5 >>>>>>> 2016-08-31 16:04:10 +0200 >>>>>>> 1 >>>>>>> avant >>>>>>> apres >>>>>>> DURANTON888 >>>>>>> 2 >>>>>>> avant >>>>>>> apres >>>>>>> VALENT >>>>>>> 3 >>>>>>> avant >>>>>>> apres >>>>>>> VIGILE1AA >>>>>>> 4 >>>>>>> avant >>>>>>> apres >>>>>>> VIGILE2 >>>>>>> 5 >>>>>>> avant >>>>>>> apres >>>>>>> DURANDTON >>>>>>> >>>>>>> >>>>>>> >>>>>>> Si vous avez une idée >>>>>>> >>>>>>> Merci beaucoup >>>>>>> >>>>>>> *Ma config* >>>>>>> >>>>>>> - Debian GNU/Linux 7 >>>>>>> - Rails 4.17 >>>>>>> - Ruby 1.91 >>>>>>> >>>>>>> -- >>>>>>> -- >>>>>>> Vous avez reçu ce message, car vous êtes abonné au groupe >>>>>>> "Railsfrance" de Google Groups. >>>>>>> Pour transmettre des messages à ce groupe, envoyez un e-mail à >>>>>>> l'adresse rails...@googlegroups.com >>>>>>> Pour résilier votre abonnement envoyez un e-mail à l'adresse >>>>>>> railsfrance...@googlegroups.com >>>>>>> --- >>>>>>> Vous recevez ce message, car vous êtes abonné au groupe >>>>>>> Google Groupes "Railsfrance". >>>>>>> Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le >>>>>>> concernant, envoyez un e-mail à l'adresse >>>>>>> railsfrance...@googlegroups.com. >>>>>>> Pour obtenir davantage d'options, consultez la page >>>>>>> https://groups.google.com/d/optout. >>>>>>> >>>>>> >>>>>> -- >>>>>> -- >>>>>> Vous avez reçu ce message, car vous êtes abonné au groupe >>>>>> "Railsfrance" de Google Groups. >>>>>> Pour transmettre des messages à ce groupe, envoyez un e-mail à >>>>>> l'adresse rails...@googlegroups.com >>>>>> Pour résilier votre abonnement envoyez un e-mail à l'adresse >>>>>> railsfrance...@googlegroups.com >>>>>> --- >>>>>> Vous recevez ce message, car vous êtes abonné au groupe >>>>>> Google Groupes "Railsfrance". >>>>>> Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le >>>>>> concernant, envoyez un e-mail à l'adresse >>>>>> railsfrance...@googlegroups.com. >>>>>> Pour obtenir davantage d'options, consultez la page >>>>>> https://groups.google.com/d/optout. >>>>>> >>>>> >>>>> -- >>> -- >>> Vous avez reçu ce message, car vous êtes abonné au groupe "Railsfrance" >>> de Google Groups. >>> Pour transmettre des messages à ce groupe, envoyez un e-mail à l'adresse >>> rails...@googlegroups.com >>> Pour résilier votre abonnement envoyez un e-mail à l'adresse >>> railsfrance...@googlegroups.com >>> --- >>> Vous recevez ce message, car vous êtes abonné au groupe Google Groupes >>> "Railsfrance". >>> Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le >>> concernant, envoyez un e-mail à l'adresse >>> railsfrance...@googlegroups.com. >>> Pour obtenir davantage d'options, consultez la page >>> https://groups.google.com/d/optout. >>> >> >> -- -- Vous avez reçu ce message, car vous êtes abonné au groupe "Railsfrance" de Google Groups. Pour transmettre des messages à ce groupe, envoyez un e-mail à l'adresse railsfrance@googlegroups.com Pour résilier votre abonnement envoyez un e-mail à l'adresse railsfrance-unsubscr...@googlegroups.com --- Vous recevez ce message, car vous êtes abonné au groupe Google Groupes Railsfrance. Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse railsfrance+unsubscr...@googlegroups.com. Pour plus d'options, visitez le site https://groups.google.com/d/optout .