¿Cómo puedo hacer que Ruby vuelva a intentar automáticamente un command varias veces?

Actualmente, nuestra ejecución de aplicaciones falla a veces, porque nuestro Gitserver es muy irreparable.

begin repository = Git.clone(remote_repo,deploy_script_root, { }) ... rescue Exception => e log.error e raise "Could not export deploy scripts: #{e.message}" end 

error: Falló la connection a gitserver: 80; La operación está en progreso mientras se accede a http: // gitserver

Me preguntaba cómo podría hacer que Ruby vuelva a intentar este command varias veces para no romper nuestras carreras.

use retry

 begin retries ||= 0 repository = Git.clone(remote_repo,deploy_script_root, { }) ... rescue Exception => e log.error e retries += 1 retry if (retries <= 5) raise "Could not export deploy scripts: #{e.message}" end 

Ruby en realidad tiene una palabra key de retry que se usa dentro del rescue para volver a intentar un bloque de código. Prueba este artículo para profundizar en las cosas.

Además, esto suena como un hack. Si hay algo que pueda hacer para arreglar el server que sea mejor que poner un hack en su código, cuando la raíz del problema parece ser que el server de git no es confiable.

Puede usar la statement de retry Ruby. retry devolverá el control de su progtwig al principio del bloque adjunto. El caso simple es este:

 begin repository = Git.clone(remote_repo,deploy_script_root, { }) # ... rescue retry end 

Usado de esta manera, esto volverá a intentarse para siempre, lo que no sería bueno para un entorno de producción. De hecho, en este punto, el código ni siquiera comtesting qué error causó la exception, por lo que está reintentando ciegamente, incluso si el error no es recuperable.

Se necesita un poco de lógica de control para que falle después de que haya fallado un número de bashs de rebash, y verificar que el error sea recuperable antes de intentar volver a intentarlo. Esto le dará una solución más robusta y elegante que el simple ejemplo de retry anterior.

Pruebe esto como punto de partida:

 # For more robust support, consider reading these from a config file MAX_RETRIES = 10 SLEEP_DURATION = 5 # Begin the retryable operation retry_count = 0 begin repository = Git.clone(remote_repo,deploy_script_root, { }) # ... rescue Exception => e log.error e # Check that it's a recoverable error, before trying to recover... allow_retry = /Failed connect to gitserver/i.match(e.message) if allow_retry && retry_count < MAX_RETRIES retry_count += 1 sleep SLEEP_DURATION retry end raise "Could not export deploy scripts: #{e.message}" end 

Con un código como este, puede controlar cuántas veces se reintenta la operación y cuánto time esperar entre rebashs. Y ahora sabe que solo se reintentan los errores recuperables, de modo que falla rápidamente cuando no se debe volver a intentar el error.