I am using Mechanize in Ruby to post forms to a site to obtain data. Occasionally, I will get the error
too many connection resets (due to Operation timed out - Errno::ETIMEDOUT) after 13 requests on 34234234234242, last used 20.518373 seconds ago
This will crash the server. I would like to catch this error and handle it(by retrying later on).
I tried
begin
postForm(form)
rescue Errno::ETIMEDOUT
puts "=====>TimeOut ERROR!:"
end
But it is not catching the error.
What am I missing?
Thanks.
It looks like Mechanize caught the Errno::ETIMEDOUT error and threw a new exception containing the error message. Therefore, the exception class name is different, and can't be caught with Errno::ETIMEDOUT.
To determine the type of error, try this:
begin
postForm(form)
rescue => e
puts e.class
end
That will give you the exception class name, and you can update the rescue clause.
If you read the entire error message, you see that you failed because of a 'too many connection resets' : The timeout is only what caused the connection to reset 13 times, and has already been rescued.
So if you read the source of Net-Http-persistent >here<, you will see that the error you need to catch is :
Net::HTTP::Persistent::Error
Related
Bugsnag reports that from time to time IO::EAGAINWaitReadable exception is raised in production.
IO::EAGAINWaitReadable: Resource temporarily unavailable - read would block
The exception is raised on HTTP request via HTTParty, ultimately leading to net/protocol.rb:153:in read_nonblock in Ruby 2.1.3.
Why do I get IO::EAGAINWaitReadable? Why are sometimes HTTP requests blocking? And why not let them block, what's the deal?
The most general way to handle IO::EAGAINWaitReadable is:
begin
result = io.read_nonblock(maxlen)
rescue IO::EAGAINWaitReadable
IO.select([io])
retry
end
So can do it without selection a port, but better with a selection as it is shewn in the example. Also you can look at the SO answer on how to trap the WaitReadable additionally to the specified.
I'm writing a Ruby program using the mysql2 gem. This program iterates over large sets of data and makes lots of individual database queries using the mysql2 .query method. Occasionally, one of them will fail (usually because it's a duplicate of a previous row), ending the program.
I'd like to change this, so that when a query fails, the information is logged to a log file, the query is skipped, and the program continues to run. But I have no idea how I would go about doing something like this. Can anyone let me know where to start reading, or what I should be doing?
Put the Code that might throw an error in an begin ... rescue ... end block:
begin
# code that might throw the database error
rescue ActiveRecord::StatementInvalid => e
puts "An error occurred: #{e.message}"
end
Not that ActiveRecord::StatementInvalid will only invalid queries (like duplicate entries), but not other errors like when the db connection died. It is good practice to catch only the most specific errors you want to handle and not all possible errors.
I am working on a rake system, and I have some new code which needs to do some consistency checking. I would like the code to not exit on the first error; I would like it to continue to finish checks on the rest of the data. If it does hit a consistency error, it can throw an exception. I am trying to use a simple construct just to catch RuntimeError:
begin
<code which may throw RuntimeError...>
rescue RuntimeError => e
<print info about exception ...>
end
This seems to execute the rescue block; the error message from the rescue is printed. The problem is that rake still aborts, even though the exception has been caught and handled. Is there some setting in rake which sets abort_on_exception to true? Is there any way yo change this? I do not want it to abort on this exception, I just want the error printed, and to continue with the rest of the checks. It will exit on a higher level if the complete consistency check reported an error. Perhaps I need to throw something other than a RuntimeError? I am just using raise with a string argument.
Can you try Exception insted of RuntimeError exception
begin
<code which may throw RuntimeError...>
rescue Exception => e
p e.message
p e.backtrace
end
I have an EventMachine server that I am monitoring with monit. Sometimes it crashes, and I am trying to figure out why, but it is unclear to me how I can just log all top level failures. I tried code like this:
begin
EventMachine::run do
EventMachine::start_server('0.0.0.0', PORT, MyServer)
end
rescue Exception => e
puts "FAILURE: #{e.class}: #{e}"
end
but that does not seem to ever catch errors. I suspect it might be something like running out of memory, which I am tracking separately, but still I would like this server to log its proximate cause of failure if possible.
If you want a catch-all error handler, try EM.error_handler. Example from the docs:
EM.error_handler{ |e|
puts "Error raised during event loop: #{e.message}"
}
You may also want more fine-grained error handling, in which case you can use the errback mechanism (see Deferrable). So for example you could have in your reactor loop:
EventMachine::run do
server = EventMachine::start_server('0.0.0.0', PORT, MyServer)
server.errback { # handle error thrown by server here }
end
For this to work, include Deferrable in your MyServer, then whenever you want to raise an error, call fail.
I have several embedded linux systems that I want to write a 'Who's Online?' network service in Ruby. Below is related part of my code:
mySocket = UDPSocket.new
mySocket.bind("<broadcast>", 50050)
loop do
begin
text, sender = mySocket.recvfrom(1024)
puts text
if text =~ /KNOCK KNOCK/ then
begin
sock = UDPSocket.open
sock.send(r.ipaddress, 0, sender[3], 50051)
sock.close
rescue
retry
end
end
rescue Exception => inLoopEx
puts inLoopEx.message
puts inLoopEx.backtrace.inspect
retry
end
end
I send the 'KNOCK KNOCK' command from a PC. Now, the problem is since they all receive the message at the same time, they try to respond at the same time too, which causes a Broken Pipe exception (which is the reason of my 'rescue retry' code). This code works OK sometimes but; other times the rescue retry part of the code (which is waked by Broken Pipe exception from sock.send) causes one or more systems to respond after 5 seconds or so.
Is there a better way of doing this since I assume I cant escape the Broken Pipe exception?
I have found that exception was caused by the 'r.ipaddress' part in the send command, which is related to my embedded system's internals...