2009-10-21 4 views
7

J'ai une application Rails dans laquelle un petit nombre d'actions nécessite un temps de calcul important. Plutôt que de passer en revue la complexité de la gestion de ces actions en tâche de fond, j'ai trouvé que je pouvais diviser le traitement en plusieurs threads et en utilisant JRuby avec un serveur multicœur, je pouvais m'assurer que tous les threads se terminent dans un délai raisonnable. (Le client a déjà manifesté un vif intérêt pour conserver cette approche par rapport à l'exécution des tâches en arrière-plan.)Connexion des threads dans une application Rails

Le problème est que l'écriture dans l'enregistreur Rails ne fonctionne pas dans ces threads. Rien n'apparaît dans le fichier journal. J'ai trouvé quelques références à ce problème mais pas de solutions. Cela ne me dérangerait pas d'insérer des puts dans mon code pour aider au débogage mais stdout semble être mangé par le serveur glassfish gem app.

Est-ce que quelqu'un a réussi à se connecter à l'intérieur d'un thread Ruby de Rails sans créer de nouveau journal à chaque fois?

+0

Mise à jour: J'ai trouvé que les puts dans les threads apparaissent dans le fichier journal de glassfish. Je ne sais pas pourquoi je n'ai pas vu ça avant; Je l'ai peut-être testé à l'origine dans un thread engendré par un autre thread (non principal). Quoi qu'il en soit, à des fins de débogage, je vois des écritures dans STDOUT dans le fichier journal, donc je suis content. –

Répondre

4

Je me grattais la tête avec le même problème. Pour moi, la réponse était la suivante:

Thread.new do 
    begin 
    ... 
    ensure 
    Rails.logger.flush 
    end 
end 
+0

Ça a l'air bien! Merci! –

+0

Ne fonctionne pas pour moi, en utilisant EM – skrat

0

Je comprends vos préoccupations au sujet des tâches d'arrière-plan, mais rappelez-vous que la suppression des threads dans Rails peut être une chose effrayante. Le framework ne comporte pratiquement aucune disposition pour le multithreading, ce qui signifie que vous devez traiter tous les objets Rails comme n'étant pas thread-safe. Même la connexion à la base de données devient compliquée. En ce qui concerne l'enregistreur: La classe Ruby logger standard doit être thread-safe. Mais même si Rails l'utilise, vous n'avez aucun contrôle sur ce que fait l'application Rails. Par exemple, le mécanisme d'analyse comparative "fera taire" l'enregistreur en changeant de niveau.

J'éviterais d'utiliser l'enregistreur de rails. Si vous souhaitez utiliser les threads, créez un nouveau journal dans le thread qui enregistre les messages pour cette opération. Si vous ne souhaitez pas créer de nouveau journal pour chaque thread, vous pouvez également essayer de créer un objet de journalisation thread-safe dans votre environnement d'exécution auquel chacun des threads peut accéder.

À votre place j'aurais probablement un autre regard sur les solutions de travail d'arrière-plan. Alors que DRb ressemble à un cauchemar, "bj" semble gentil et facile; Bien qu'il ait fallu du travail pour le faire fonctionner avec JRuby. Il y a aussi l'alternative d'utiliser un planificateur Java de JRuby, voir http://www.jkraemer.net/2008/1/12/job-scheduling-with-jruby-and-rails

+0

Merci pour les informations et suggestions, mais à ce stade, je vais rester avec l'approche de threading, car il fonctionne bien, sauf pour la journalisation. Je n'utilise pas de gems/plugins discutable dans aucun des threads et je fais attention à l'utilisation des mutex pour éviter les conditions de course. Mon intérêt pour l'utilisation de l'enregistreur Rails était simplement la facilité du débogage et j'ai réussi à contourner cela en utilisant des threads seulement si JRUBY_VERSION est défini et sinon en exécutant le même code séquentiellement. Merci quand même! –

Questions connexes