2009-07-29 14 views
6

Ich entwickle eine kleine Anwendung, die XML an einige Web-Service sendet. Dies geschieht mit Net :: HTTP :: Post :: Post. Der Dienstanbieter empfiehlt jedoch, eine erneute Verbindung zu verwenden.Implementieren Re-connect-Strategie mit Ruby Net

Etwas wie: erste Anforderung fehlschlägt -> versuchen Sie es erneut nach 2 Sekunden 2. Anforderung fehlschlägt -> versuchen Sie es erneut nach 5 Sekunden 3. Anforderung fehlschlägt -> versuchen Sie es erneut nach 10 Sekunden ...

Was würde ein guter Ansatz sein, das zu tun? Einfach das folgende Stück Code in einer Schleife ausführen, die Ausnahme abfangen und nach einiger Zeit erneut ausführen? Oder gibt es einen anderen cleveren Weg, das zu tun? Vielleicht hat das Net-Paket sogar eine eingebaute Funktionalität, die mir nicht bekannt ist?

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)} 

Vielen Dank, immer zu schätzen Ihre Unterstützung.

Matt

Antwort

15

Dies ist eine der seltenen Gelegenheiten, bei denen Rubys retry kommt in handliches. Etwas in diesen Zeilen:

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

Excellent Mit ihm aus transformierten Code. Vielen Dank! – Matt

+0

Avdi, was ist eine gute Möglichkeit, das zu testen? (mit rspec oder anderen) – Mike

+0

Danke. Btw scheint, 'SomeException' muss leider' StandardError' sein, siehe: http://stackoverflow.com/questions/5370697/what-s-the-best-way-to-handle-exceptions-from-nethttp. Nicht großartig, aber zumindest ist es auf eine Linie beschränkt und wird nicht verschluckt, wenn es sich um einen nicht vorübergehenden, tatsächlichen Fehler handelt. – chesterbr

2

Ich benutze Edelstein retryable für Wiederholung.

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 

zu:

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

nettes Juwel thx für die Spitze – daniel

+0

sie sind nicht gleich: zuerst tut 4 Bindungen mit Verzögerungen 0,3,5,10; Sekunde macht 10 Versuche mit 1 Sekunde Verzögerung. – hlcs