Tiempo de espera de Ruby / Rails con hilos: cómo esperar un momento y luego volver a unirse más tarde.
Estoy tratando de ejecutar un proceso en un hilo y, si tarda más de x segundos, redireccionar a una página de espera y luego hacer una actualización ajax.
begin
Timeout::timeout(10) do
t = Thread.new do
begin
output = do_work
session[:result] = "hecho"
rescue Exception => e
session[:result] = "excepción"
end
end
t.join
end
if session[:result] == "hecho"
redirect_to :done
else
redirect_back fallback_location: :root, notice: 'No se puede procesar la solicitud, por favor inténtelo de nuevo.'
end
rescue Exception => e
if e.message == "execution expired"
# esto significa que ha expirado el tiempo de espera, así que redirígelos a "waiting"
redirect_to waiting_path
else
redirect_back fallback_location: :root, notice: 'No se puede procesar la solicitud, por favor inténtelo de nuevo.'
end
end
Luego, en la página “waiting”, verifica el resultado.
def waiting
# session[:result] nunca se actualiza
end
¿Qué estoy haciendo mal? Esperaría que si se produce una excepción, el hilo sobreviva, como se evidencia en este experimento simple:
begin
Timeout::timeout(1) do
t = Thread.new do
sleep(5)
puts "¡Hecho!"
end
t.join
end
rescue Exception => e
if e.message == "execution expired"
# esto significa que ha expirado el tiempo de espera, así que imprime "expired"
puts "¡Expirado!"
end
end
El código anterior funciona bien y después de 5 segundos, el hilo se completa y muestra la salida.
¿Es esto porque no se puede establecer la sesión en un hilo o algo similar?
Gracias por cualquier ayuda,
Kevin
davy.ai
Hola Kevin,
Parece que el problema está relacionado con el hecho de que estás intentando acceder a la sesión en un hilo separado. Rails utiliza un modelo de solicitud/respuesta, por lo que la sesión está vinculada al ciclo específico de solicitud/respuesta. Cuando ejecutas un hilo en segundo plano, no tiene acceso a la sesión durante el ciclo principal de solicitud/respuesta.
Una forma de solucionar esto es utilizar una caché compartida o una base de datos para almacenar el resultado del proceso en segundo plano. En lugar de establecer la variable de sesión en el hilo, podrías actualizar un registro de base de datos o una entrada de caché con el resultado, y luego verificar ese valor actualizado en la acción de espera. Luego, puedes utilizar una llamada AJAX para verificar periódicamente el valor actualizado y actualizar la página cuando esté disponible.
Otra opción sería utilizar un sistema de cola de mensajes, como Sidekiq o Resque, para manejar tareas en segundo plano. Estos sistemas te permiten agregar una tarea a una cola, que luego es procesada por un proceso de trabajador separado. El proceso de trabajador puede actualizar la base de datos/caché según sea necesario, y luego puedes usar AJAX para verificar el valor actualizado como antes.
¡Espero que esto sea de ayuda! Avísame si tienes alguna otra pregunta.
Saludos,
[Tu Nombre]