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 
> <javascript:>>:
>
>> 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 <javascript:>
>> Pour résilier votre abonnement envoyez un e-mail à l'adresse 
>> railsfrance...@googlegroups.com <javascript:>
>> --- 
>> 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 
>> <javascript:>.
>> 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 .

Répondre à