Una posibilidad es que su hilo no se cuelga, en realidad muere. Esto es lo que debe hacer para descubrir qué está pasando. Añadir este antes de crear el subproceso de trabajo:
Thread.abort_on_exception = true
Cuando se produce una excepción dentro de su hilo que no está atrapado, todo el proceso se termina, y se puede ver qué excepción fue levantado. De lo contrario (y este es el valor predeterminado), su hilo se mata.
Si esto resulta no ser el problema, sigue leyendo ...
implementación de los tiempos de espera de Ruby es bastante ingenuo. Configura un hilo separado que duerme durante n segundos, luego levanta ciegamente una excepción de tiempo de espera dentro del hilo original.
Ahora, el código original en realidad podría estar en el medio de un bloque rescue
o ensure
. Al generar una excepción en dicho bloque se cancelará silenciosamente cualquier tipo de código de limpieza. Esto podría dejar el código que se agota en un estado incorrecto.
Es bastante difícil determinar si este es su problema exactamente, pero al ver cómo los manejadores de base de datos podrían hacer un poco de bloqueo y manejo de excepciones, podría ser muy probable. Here's an article that explains the issue in more depth.
¿Hay alguna forma de que pueda utilizar el manejo de tiempo de espera integrado de la biblioteca de su base de datos? Puede implementarse en un nivel inferior, sin utilizar la implementación de tiempo de espera de Ruby.
Una alternativa simple es programar las llamadas a la base de datos en un proceso separado. Puede bifurcar el proceso principal cada vez que realice una pesada carga de base de datos. O puede configurar un cronjob simple para ejecutar un script que lo ejecute. Esto será un poco más difícil si necesita comunicarse con su hilo principal. Por favor, deje algunos detalles más si desea algún consejo sobre qué opción puede satisfacer sus necesidades.
Según sus comentarios, el hilo está muriendo. Esto podría ser un error en las bibliotecas o en el código de la aplicación que puede o no ser capaz de corregir.Si desea atrapar cualquier error arbitrario que se genera por el código de gestión de base de datos y, posteriormente, volver a intentar, puede intentar algo como lo siguiente:
t = Thread.new do
loop do
sleep INTERVAL
begin
# Execute database queries and process data
rescue StandardError
# Log error or recover from error situation before retrying
end
end
end
También puede utilizar la palabra clave retry
en el bloque rescue
volver a intentar, pero es probable que deba mantener un contador para asegurarse de no volver a intentar accidentalmente de forma indefinida cuando se produce un error irrecuperable.
Así que no está tirando Tiempo de espera :: ¿Error? ¿Está arrojando algún error? –
Correcto, no pasa nada, simplemente se congela justo donde está. Al menos, eso es lo que he determinado al poner 'puts' excesivas en todas partes para determinar dónde/si la ejecución se recogió una copia de seguridad. –
¿Por qué estaría haciendo eso tirar? El punto de espera total debería ser que genera un error si el bloque que se ejecuta se ejecuta durante demasiado tiempo. He intentado con datamapper y mysql2 directamente, esperando o hacer una reconexión automática y resolver el problema de esa manera, pero sin suerte. Si los detalles ayudan, digamos que es una conexión mysql2 en la que hago un '.query (...)'. Nunca se arroja nada desde allí, de todos modos, y una cláusula genérica de 'rescate' fuera debería atraparlo en cualquier caso. –