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é
-
le render dans ma boucle each ne fonctionne évidemment pas car on
ne peut pas faire des rendus multiples -
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. -
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.
- 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.