Sequel gem: Handling invalid date values gracefully - ruby

I'm a ruby noob and I'm trying to process some blog posts using Sequel and the data_objects adapter:
DB = Sequel.connect('do:mysql://user:pass#localhost/database')
db[posts_query].each do |post|
puts post
end
But I get Sequel::InvalidValue exception, complaining about the date column:
/usr/lib/ruby/1.9.1/time.rb:202:in `local': ArgumentError: argument out of range (Sequel::InvalidValue)
from /usr/lib/ruby/1.9.1/time.rb:202:in `make_time'
from /usr/lib/ruby/1.9.1/time.rb:271:in `parse'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/core.rb:295:in `string_to_datetime'
I tried to catch the exception:
begin
db[posts_query].each do |post|
puts post
end
rescue Sequel::InvalidValue => e
puts e.inspect
end
but that doesn't help much.
How can I find out which row has the incorrect value?
Also, is there a way to do this iteration, such that I can catch the exception but continue to loop over the remaining rows?
Update:
I switched to the mysql2 adapter and now I can at least see the invalid date:
/var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/adapters/mysql2.rb:154:in `each': Mysql2::Error: Invalid date: 2008-04-00 00:00:15 (Sequel::DatabaseError)
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/adapters/mysql2.rb:154:in `block in fetch_rows'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/adapters/mysql2.rb:89:in `_execute'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/adapters/shared/mysql_prepared_statements.rb:34:in `block in execute'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/database/connecting.rb:236:in `block in synchronize'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/connection_pool/threaded.rb:104:in `hold'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/database/connecting.rb:236:in `synchronize'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/adapters/shared/mysql_prepared_statements.rb:34:in `execute'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/dataset/actions.rb:778:in `execute'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/adapters/mysql2.rb:171:in `execute'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/adapters/mysql2.rb:140:in `fetch_rows'
from /var/lib/gems/1.9.1/gems/sequel-3.42.0/lib/sequel/dataset/actions.rb:154:in `each'
from wordpress_importer.rb:112:in `process'
from wordpress_importer.rb:308:in `<main>'

Can you post more of the backtrace? You need to see what is calling string_to_datetime.
Also, I would recommend against using the do/mysql adapter unless you have specific needs that require it. Use the mysql or mysql2 adapter instead. If the error is being caused by bogus datetimes in your MySQL database, then you may want to use the mysql2 adapter or use the mysql adapter and set DB.convert_invalid_date_time = nil.

Related

PG::ConnectionBad: PQconsumeInput() SSL error: key values mismatch

When I open a certificate with OpenSSL::PKCS12, I lose the connection with my database and occur the error: PG::ConnectionBad: PQconsumeInput() SSL error: key values mismatch.
I'm doing this:
myuser#developer:~/myapp$ rails c
2.2.3 :001 > OpenSSL::PKCS12.new File.read('/local/to/mycert.pfx'), 'PASSWORD'
=> #<OpenSSL::PKCS12:0x000000072e6808 #key=#<OpenSSL::PKey::RSA:0x000000072e67e0>, #certificate=#<OpenSSL::X509::Certificate: subject=#<OpenSSL::X509::Name:0x000000072e6100>, issuer=#<OpenSSL::X509::Name:0x000000072e6128>, serial=#<OpenSSL::BN:0x000000072e6150>, not_before=2014-12-18 19:15:55 UTC, not_after=2015-12-18 19:15:55 UTC>,
#ca_certs=[#<OpenSSL::X509::Certificate: subject=#<OpenSSL::X509::Name:0x000000072e5c78>, issuer=#<OpenSSL::X509::Name:0x000000072e5ca0>, serial=#<OpenSSL::BN:0x000000072e5cc8>, not_before=2014-08-04 18:38:36 UTC, not_after=2021-10-11 18:38:36 UTC>, #<OpenSSL::X509::Certificate: subject=#<OpenSSL::X509::Name:0x000000072e5818>, issuer=#<OpenSSL::X509::Name:0x000000072e5840>, serial=#<OpenSSL::BN:0x000000072e5868>, not_before=2011-10-21 12:16:29 UTC, not_after=2021-10-21 12:16:29 UTC>, #<OpenSSL::X509::Certificate: subject=#<OpenSSL::X509::Name:0x000000072e52f0>, issuer=#<OpenSSL::X509::Name:0x000000072e5318>, serial=#<OpenSSL::BN:0x000000072e5340>, not_before=2010-06-21 19:04:57 UTC, not_after=2023-06-21 19:04:57 UTC>]>
After this I lose the connection:
2.2.3 :002 > Company.last
PG::ConnectionBad: PQconsumeInput() SSL error: key values mismatch
: SELECT tablename
FROM pg_tables
WHERE schemaname = ANY (current_schemas(false))
ActiveRecord::StatementInvalid: PG::ConnectionBad: PQconsumeInput() SSL error: key values mismatch
: SELECT tablename
FROM pg_tables
WHERE schemaname = ANY (current_schemas(false))
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:147:in `async_exec'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:147:in `block in query'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/connection_adapters/abstract_adapter.rb:473:in `block in log'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activesupport-4.2.4/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/connection_adapters/abstract_adapter.rb:467:in `log'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:146:in `query'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/connection_adapters/postgresql/schema_statements.rb:91:in `tables'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/connection_adapters/schema_cache.rb:90:in `prepare_tables'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/connection_adapters/schema_cache.rb:22:in `table_exists?'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/model_schema.rb:230:in `table_exists?'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/attribute_methods/primary_key.rb:97:in `get_primary_key'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/attribute_methods/primary_key.rb:85:in `reset_primary_key'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/attribute_methods/primary_key.rb:73:in `primary_key'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/attribute_methods/primary_key.rb:80:in `quoted_primary_key'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/relation/delegation.rb:48:in `quoted_primary_key'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/relation/query_methods.rb:1078:in `reverse_sql_order'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/relation/query_methods.rb:852:in `reverse_order!'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/relation/query_methods.rb:846:in `reverse_order'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/relation/finder_methods.rb:511:in `find_last'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/relation/finder_methods.rb:160:in `last'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/activerecord-4.2.4/lib/active_record/querying.rb:3:in `last'
from (irb):2
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/railties-4.2.4/lib/rails/commands/console.rb:110:in `start'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/railties-4.2.4/lib/rails/commands/console.rb:9:in `start'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:68:in `console'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
from /home/myuser/.rvm/gems/ruby-2.2.3/gems/railties-4.2.4/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'2.2.3 :003 >
I perceive that this occurs when the method ca_certs is not null.
Ruby version: 2.2.3
Rails version: 4.2.4
gem 'pg', '0.18.3'
Has anyone had this problem?
I encountered this same problem today. After a long search I came across this thread. Seems like a bug in OpenSSL library/extension. Because opening a certificate and talking to a DB happen in a single thread, the connection gets screwed up. I still haven't figured out all details but a workaround is to open the certificate in it's own thread, like:
pkcs = nil
Thread.new { pkcs = OpenSSL::PKCS12.new File.read('/local/to/mycert.pfx'), 'PASSWORD' }.join
Hope that helps :)

Error while upgrading from Rails 3.1 to Rails 3.2

Upgrade steps were performed as mentioned in http://guides.rubyonrails.org/3_2_release_notes.html
Right now I'm on Ruby 1.8.7 and Rails 3.1.x (using system ruby). I installed RVM with ruby 1.8.7 and added to rails 3.2 and then I get the following error:
[app]$ rails console
Faraday: you may want to install system_timer for reliable timeouts
$HOME/src/qbol/tapp/config/environment.rb:16:in `add': undefined method `>' for nil:NilClass (NoMethodError)
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/tagged_logging.rb:55:in `add'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/tagged_logging.rb:61:in `info'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activerecord-3.2.17/lib/active_record/railtie.rb:86
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/lazy_load_hooks.rb:36:in `instance_eval'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/lazy_load_hooks.rb:36:in `execute_hook'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/lazy_load_hooks.rb:26:in `on_load'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/lazy_load_hooks.rb:25:in `each'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/lazy_load_hooks.rb:25:in `on_load'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activerecord-3.2.17/lib/active_record/railtie.rb:80
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/railties-3.2.17/lib/rails/initializable.rb:30:in `instance_exec'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/railties-3.2.17/lib/rails/initializable.rb:30:in `run'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/railties-3.2.17/lib/rails/initializable.rb:55:in `run_initializers'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/railties-3.2.17/lib/rails/initializable.rb:54:in `each'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/railties-3.2.17/lib/rails/initializable.rb:54:in `run_initializers'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/railties-3.2.17/lib/rails/application.rb:136:in `initialize!'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/railties-3.2.17/lib/rails/railtie/configurable.rb:30:in `send'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/railties-3.2.17/lib/rails/railtie/configurable.rb:30:in `method_missing'
from $HOME/src/app/config/environment.rb:48
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/dependencies.rb:251:in `require'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/dependencies.rb:251:in `require'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/dependencies.rb:236:in `load_dependency'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/activesupport-3.2.17/lib/active_support/dependencies.rb:251:in `require'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/railties-3.2.17/lib/rails/application.rb:103:in `require_environment!'
from $HOME/.rvm/gems/ruby-1.8.7-p374/gems/railties-3.2.17/lib/rails/commands.rb:40
from script/rails:6:in `require'
from script/rails:6
This is on my development box. Any idea why this is happening?
EDIT: Below is the environment.rb. The error is happening on the last line App::Application.initialize!
# Load the rails application
require File.expand_path('../application', __FILE__)
module ActiveSupport
class BufferedLogger
def self.current_user
Thread.current[:user]
end
def self.current_user=(user)
Thread.current[:user] = user
end
def add(severity, message = nil, progname = nil, &block)
return if #level > severity
message = (message || (block && block.call) || progname).to_s
level = {
0 => "DEBUG",
1 => "INFO ",
2 => "WARN ",
3 => "ERROR",
4 => "FATAL"
}[severity] || "UNKNOWN"
user=BufferedLogger.current_user
if(!user.nil?)
idstr = "uid:#{user.id}"
if !user.current_app_user.nil?
idstr.concat(", acid: #{user.current_app_user.account_id}")
end
else
idstr=""
end
message = "[%s: %s #{idstr}] %s" %
["#{level} pid: #{$$}", Time.now.strftime("%y-%m-%d %H:%M:%S"), message]
message = "#{message}\n" unless message[-1] == ?\n
buffer << message
auto_flush
message
end
end
end
# Initialize the rails application
App::Application.initialize!
The error is happening inside ActiveSupport::BufferedLogger#add method call and you appear to be monkey-patching this class. The internals of ActiveSupport::BufferedLogger have likely changing between the versions of Rails you're using.
Try removing all of the ActiveSupport::BufferedLogger code from your environment.rb to work past this error and get your app running. Then, if you still need the monkeypatch (don't know why), you'd have to rewrite it on top of the newer version of the class.

Cannot read span elements

Hi since I did gem install watir watir-classic my scripts are not reading anymore the span elements. Can you please help me to fix this problem
here my example
Source
Rented
<SPAN class="displayData" style="padding-left:2px; width: 15;"><span name="tab4RateInfoForm.vehicleGroup"/>F</span></SPAN>
My code
carGroup=browser.span(:name => 'tab4RateInfoForm.vehicleGroup').text
Error message
C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:79:in `rescue in match?': name is an unknown way of finding a <span> element (tab4RateInfoForm.vehicleGroup) (Watir::Exception::MissingWayOfFindingObjectException)
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:76:in `match?'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:62:in `block in match_with_specifiers?'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:59:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:59:in `all?'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:59:in `match_with_specifiers?'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:22:in `block (2 levels) in each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:140:in `block in each_element'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:139:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:139:in `each_element'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:21:in `block in each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:20:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:20:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/locator.rb:150:in `locate'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/element.rb:33:in `locate'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/element.rb:63:in `assert_exists'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.3.0/lib/watir-classic/element.rb:132:in `text'
Solution 1: Use css locator
You will have to use a css-locator (or xpath):
carGroup = browser.span(:css, 'span[name="tab4RateInfoForm.vehicleGroup"]').text
Solution 2: Monkey patch
Alternatively, if you have a lot of legacy scripts that use the name attribute, you can monkey patch Watir to have the name method for all elements (or specific element if desired).
Add the following to wherever you require watir:
Watir::IE.new(true)
module Watir
class Element
def name
return self.attribute_value('name')
end
end
end
Your original method should now work.
Looks like span elements can no longer be accessed via name attribute.
Try this (use generic element instead of span):
carGroup=browser.element(:name => 'tab4RateInfoForm.vehicleGroup').text

How do I catch this exception in Ruby?

I'm a ruby beginner so bear with me.
I am using the selenium-webdriver and rb-appscript gems to do some webscraping. The navigation to websites seems to be driven by the Net::Http object, which has a rbuf_fill method.
Running the following code:
sites = File.open("sites.txt", "r") if File::exists?( "sites.txt" )
if sites != nil
while (line = sites.gets)
driver.switch_to.default_content
begin
driver.navigate.to line
rescue Exception
line = line.split.join("\n")
puts line + " caused a timeout."
end
end
...
Produces this error:
/opt/local/lib/ruby1.9/1.9.1/net/protocol.rb:140:in `rescue in rbuf_fill': Timeout::Error (Timeout::Error)
from /opt/local/lib/ruby1.9/1.9.1/net/protocol.rb:134:in `rbuf_fill'
from /opt/local/lib/ruby1.9/1.9.1/net/protocol.rb:116:in `readuntil'
from /opt/local/lib/ruby1.9/1.9.1/net/protocol.rb:126:in `readline'
from /opt/local/lib/ruby1.9/1.9.1/net/http.rb:2219:in `read_status_line'
from /opt/local/lib/ruby1.9/1.9.1/net/http.rb:2208:in `read_new'
from /opt/local/lib/ruby1.9/1.9.1/net/http.rb:1191:in `transport_request'
from /opt/local/lib/ruby1.9/1.9.1/net/http.rb:1177:in `request'
from /opt/local/lib/ruby1.9/1.9.1/net/http.rb:1170:in `block in request'
from /opt/local/lib/ruby1.9/1.9.1/net/http.rb:627:in `start'
from /opt/local/lib/ruby1.9/1.9.1/net/http.rb:1168:in `request'
from /opt/local/lib/ruby1.9/gems/1.9.1/gems/selenium-webdriver-2.2.0/lib/selenium/webdriver/remote/http/default.rb:73:in `response_for'
from /opt/local/lib/ruby1.9/gems/1.9.1/gems/selenium-webdriver-2.2.0/lib/selenium/webdriver/remote/http/default.rb:41:in `request'
from /opt/local/lib/ruby1.9/gems/1.9.1/gems/selenium-webdriver-2.2.0/lib/selenium/webdriver/remote/http/common.rb:34:in `call'
from /opt/local/lib/ruby1.9/gems/1.9.1/gems/selenium-webdriver-2.2.0/lib/selenium/webdriver/remote/bridge.rb:406:in `raw_execute'
from /opt/local/lib/ruby1.9/gems/1.9.1/gems/selenium-webdriver-2.2.0/lib/selenium/webdriver/remote/bridge.rb:384:in `execute'
from /opt/local/lib/ruby1.9/gems/1.9.1/gems/selenium-webdriver-2.2.0/lib/selenium/webdriver/remote/bridge.rb:171:in `switchToDefaultContent'
from /opt/local/lib/ruby1.9/gems/1.9.1/gems/selenium-webdriver-2.2.0/lib/selenium/webdriver/common/target_locator.rb:68:in `default_content'
from auto.rb:25:in `<main>'
I have no idea why I can't catch this exception. Using rescue Exception should catch everything, but as you can see my script still crashes.
I have also found sources that say you must catch the timeout explicitly so I also tried:
rescue Timeout::Error
without any luck.
Any help is greatly appreciated on this one.
Ruby version: ruby 1.9.2p290 (2011-07-09 revision 32553)
OS: MacOS Snow Leopard 10.6.8 64-bit
Selenium Webdriver version: 2.2.0
The file 'timeout.rb' in Ruby's standard library defines:
module Timeout
# Raised by Timeout#timeout when the block times out.
class Error < RuntimeError
So what you need to rescue is not Timeout::Exception but rather Timeout::Error or more generically RuntimeError. Then it should work.

Rescue Timeout::Error from Redis Gem (Ruby)

I need to rescue a Timeout::Error raised from a the Redis library but i'm running into a problem, rescuing that specific class doesn't seem to work.
begin
Redis.new( { :host => "127.0.0.X" } )
rescue Timeout::Error => ex
end
=> Timeout::Error: Timeout::Error from /Users/me/.rvm/gems/ree-1.8.7-2011.03#gowalla/gems/redis-2.2.0/lib/redis/connection/hiredis.rb:23:in `connect'
When i try to rescue Exception it still doesn't work
begin
Redis.new( { :host => "127.0.0.X" } )
rescue Exception => ex
end
=> Timeout::Error: Timeout::Error from /Users/me/.rvm/gems/ree-1.8.7-2011.03#gowalla/gems/redis-2.2.0/lib/redis/connection/hiredis.rb:23:in `connect'
If i try to raise the exception manually, i can rescue it but don't know why i can't rescue it when it's called from within the Redis Gem (2.2.0).
begin
raise Timeout::Error
rescue Timeout::Error => ex
puts ex
end
Timeout::Error
=> nil
Any clue how to rescue this exception?
You ran this code in irb, right? The exception you are getting is not actually being raised by Redis.new. It is being raised by the inspect method, which irb calls to show you the value of the expression you just typed.
Just look at the stack trace (I shortened the paths to make it legible):
ruby-1.8.7-p330 :009 > Redis.new(:host => "google.com")
Timeout::Error: time's up!
from /.../SystemTimer-1.2.3/lib/system_timer/concurrent_timer_pool.rb:63:in `trigger_next_expired_timer_at'
from /.../SystemTimer-1.2.3/lib/system_timer/concurrent_timer_pool.rb:68:in `trigger_next_expired_timer'
from /.../SystemTimer-1.2.3/lib/system_timer.rb:85:in `install_ruby_sigalrm_handler'
from /..../lib/ruby/1.8/monitor.rb:242:in `synchronize'
from /.../SystemTimer-1.2.3/lib/system_timer.rb:83:in `install_ruby_sigalrm_handler'
from /.../redis-2.2.2/lib/redis/connection/ruby.rb:26:in `call'
from /.../redis-2.2.2/lib/redis/connection/ruby.rb:26:in `initialize'
from /.../redis-2.2.2/lib/redis/connection/ruby.rb:26:in `new'
from /.../redis-2.2.2/lib/redis/connection/ruby.rb:26:in `connect'
from /.../SystemTimer-1.2.3/lib/system_timer.rb:60:in `timeout_after'
from /.../redis-2.2.2/lib/redis/connection/ruby.rb:115:in `with_timeout'
from /.../redis-2.2.2/lib/redis/connection/ruby.rb:25:in `connect'
from /.../redis-2.2.2/lib/redis/client.rb:227:in `establish_connection'
from /.../redis-2.2.2/lib/redis/client.rb:23:in `connect'
from /.../redis-2.2.2/lib/redis/client.rb:247:in `ensure_connected'
from /.../redis-2.2.2/lib/redis/client.rb:137:in `process'
... 2 levels...
from /.../redis-2.2.2/lib/redis/client.rb:46:in `call'
from /.../redis-2.2.2/lib/redis.rb:90:in `info'
from /..../lib/ruby/1.8/monitor.rb:242:in `synchronize'
from /.../redis-2.2.2/lib/redis.rb:89:in `info'
from /.../redis-2.2.2/lib/redis.rb:1075:in `inspect'
from /..../lib/ruby/1.8/monitor.rb:242:in `synchronize'
from /.../redis-2.2.2/lib/redis.rb:1074:in `inspect'
from /..../lib/ruby/1.8/irb.rb:310:in `output_value'
from /..../lib/ruby/1.8/irb.rb:159:in `eval_input'
from /..../lib/ruby/1.8/irb.rb:271:in `signal_status'
from /..../lib/ruby/1.8/irb.rb:155:in `eval_input'
from /..../lib/ruby/1.8/irb.rb:154:in `eval_input'
from /..../lib/ruby/1.8/irb.rb:71:in `start'
from /..../lib/ruby/1.8/irb.rb:70:in `catch'
from /..../lib/ruby/1.8/irb.rb:70:in `start'
from /..../bin/irb:17
As you can see above, the exception occurs inside inspect, not Redis.new. When you call inspect on a Redis object, instead of just printing out its state it actually does a lot of things. In this case, inspect attempts to connect to the server and throws an exception when that times out. This seems like a very bad design to me and maybe we should file a bug report to the maintainers of the Redis gem.
This leads to some interesting behavior in IRB:
Typing Redis.new(:host => "google.com") results in an exception as shown above
Typing Redis.new(:host => "google.com"); 'hello' results in '=> "hello"'
If you want to catch this exception, try calling ensure_connected inside your begin/rescue/end block.

Resources