Requête lente et ajax

Bonjour,

Dans mon appli, j’ai un controller qui effectue une action assez lente
(plus de 5 minutes).
J’ai optimisé ma requête par tous les côtés, mais malgré tout, cela
reste très très lent.

Afin que la requête ne se perde pas en timeout, je fais de l’ajax avec
le rendu final :

render :update { |page| page.replace_html(‘my_div’, ‘resultat’) }

Jusque-là, aucun problème. Mais je voudrais pouvoir afficher l’état de
progression du travail en pourcentage
effectué.J’ai trouvé plein d’exemples de codes affichant des spinners pour
indiquer que le serveur travaille, mais ça ne me
convient pas. Typiquement, je voudrais que toutes les 5 secondes, il y
ait un rafraichissement de mon div pour
afficher le taux de progression.

Voilà mon code très épuré :

def bulk_update
input = params[:input_data]

input.each_index do |i|
parse_line(input[i])
session[:percent] = 100.0 * i / input.size
end
end

Je voudrais que régulièrement, rails me fasse un rendu
render :update { |page| page.replace_html(“my_div”, “#{session
[:percent]}% effectué”) }

Voilà ce que j’ai essayé

  1. le render dans ma boucle each ne fonctionne évidemment pas car on
    ne peut pas faire des rendus multiples

  2. englober ma boucle each dans un render(:update) do |page| … end
    mais dans ce bloc, la méthode parse_line n’est pas connue, et mes
    variables d’instances non plus.

  3. mettre la boucle each dans une thread
    thread = Thread.new {
    input.each_index do … end
    }

render :update do |page|
while thread.alive? do
page.replace_html(“my_div”, “#{session[:percent]}% effectué”)
sleep(5)
end
end

thread.join

Là, ça marche presque. En ajoutant des logger.info() un peu partout,
je vois que toutes les 5 secondes,
je réexécute le contenu de ma boucle while, mais aucun rendu n’est
fait au fur et à mesure. Tous les rendus
sont effectués à la fin (après le thread.join)

C’est encore plus flagrant si au lieu du sleep(5), je fais

page.delay(5) do
page.replace_html(“my_div”, “#{session[:percent]}% effectué”)
end

Quand ma requête est terminée, je vois 0% effectué, 5 secondes plus
tard, 20% effectué, 5 secondes plus tard,
40% effectué. Ce qui montre bien que toutes les opérations de rendu
sont effectuées en toute fin.

  1. J’ai essayé de tout faire en javascript, avec un new
    Ajax.PeriodicalUpdater qui effectue une requete toute simple
    toutes les 5 secondes

def bulk_update_percent
render :text => “#{session[:percent]}%
effectué” end

mais ces requêtes-là, sont traitées après la fin de l’exécution de ma
requête lente…

Voilà… je suis à court d’idées pour faire ce que je souhaite. Merci
de tout idée ou explication pour m’éclairer.

Hello,

si j’ai bien compris, tu essaies de processer l’action qui dure 5
minutes pendant ta requête rails, c’est ça ?

Si c’est bien le cas et à moins que ça soit une appli que tu es
vraiment tout seul à utiliser (ex: appli desktop rails localhost) il
serait vraiment préférable que tu utilises un background-runner (ex:
http://backgroundrb.rubyforge.org/) pour réaliser le processing.

Ressources:

Thibaut

http://www.learnivore.com
http://blog.logeek.fr

Bonjour,

Je ne serai pas la seule à utiliser cette application.
Merci pour les liens, je pense en effet que c’est ce dont j’ai besoin.