2009-07-29 17 views
6

Estoy desarrollando una pequeña aplicación que envía mensajes XML a algún servicio web. Esto se hace usando Net :: HTTP :: Post :: Post. Sin embargo, el proveedor de servicios recomienda usar una reconexión.Implementando la estrategia de reconexión usando Ruby Net

Algo así como: primera petición falla -> inténtelo de nuevo después de 2 segundos segunda petición falla -> intentarlo de nuevo después de 5 segundos tercera petición falla -> intentarlo de nuevo después de 10 segundos ...

Qué haría ser un buen enfoque para hacer eso? ¿Simplemente ejecutando la siguiente pieza de código en un bucle, capturando la excepción y volviéndola a ejecutar después de un período de tiempo? ¿O hay alguna otra manera inteligente de hacer eso? ¿Tal vez el paquete Net incluso tiene alguna funcionalidad incorporada de la que no tengo conocimiento?

url = URI.parse("http://some.host") 

request = Net::HTTP::Post.new(url.path) 

request.body = xml 

request.content_type = "text/xml" 


#run this line in a loop?? 
response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)} 

Muchas gracias, siempre apreciamos su apoyo.

Matt

Respuesta

15

Ésta es una de las raras ocasiones en que Ruby retry viene muy bien. Algo en esta línea:

retries = [3, 5, 10] 
begin 
    response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)} 
rescue SomeException # I'm too lazy to look it up 
    if delay = retries.shift # will be nil if the list is empty 
    sleep delay 
    retry # backs up to just after the "begin" 
    else 
    raise # with no args re-raises original error 
    end 
end 
+0

excelente. ¡Gracias! – Matt

+0

Avdi, ¿cuál es una buena manera de probar esto? (usando rspec o cualquiera) – Mike

+0

Gracias. Por cierto, parece que 'SomeException' debe ser, lamentablemente, 'StandardError', cf: http://stackoverflow.com/questions/5370697/what-s-the-best-way-to-handle-exceptions-from-nethttp. No es genial, pero al menos tiene un alcance en una línea y no se ingiere si se trata de un error real no transitorio. – chesterbr

2

Utilizo gem retryable para volver a intentarlo. Con él Código transformado de:

retries = [3, 5, 10] 
begin 
    response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)} 
rescue SomeException # I'm too lazy to look it up 
    if delay = retries.shift # will be nil if the list is empty 
    sleep delay 
    retry # backs up to just after the "begin" 
    else 
    raise # with no args re-raises original error 
    end 
end 

Para:

retryable(:tries => 10, :on => [SomeException]) do 
    response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)} 
end 
+1

gema agradable thx para la punta – daniel

+0

no son iguales: primero está haciendo 4 lazos con retrasos 0,3,5,10; el segundo es hacer 10 intentos con 1 segundo de retraso. – hlcs

Cuestiones relacionadas