require 'unit_spec_helper' require 'rpush/daemon/store/active_record/reconnectable' describe Rpush::Daemon::Store::ActiveRecord::Reconnectable do class TestDouble include Rpush::Daemon::Store::ActiveRecord::Reconnectable attr_reader :name def initialize(error, max_calls) @error = error @max_calls = max_calls @calls = 0 end def perform with_database_reconnect_and_retry do @calls += 1 raise @error if @calls <= @max_calls end end end let(:adapter_error_class) do case $adapter when 'postgresql' PGError when 'mysql' Mysql::Error when 'mysql2' Mysql2::Error when 'jdbcpostgresql' ActiveRecord::JDBCError when 'jdbcmysql' ActiveRecord::JDBCError when 'jdbch2' ActiveRecord::JDBCError when 'sqlite3' SQLite3::Exception else raise "Please update #{__FILE__} for adapter #{$adapter}" end end let(:error) { adapter_error_class.new("db down!") } let(:test_double) { TestDouble.new(error, 1) } before do @logger = double("Logger", :info => nil, :error => nil, :warn => nil) Rpush.stub(:logger).and_return(@logger) ActiveRecord::Base.stub(:clear_all_connections!) ActiveRecord::Base.stub(:establish_connection) test_double.stub(:sleep) end it "should log the error raised" do Rpush.logger.should_receive(:error).with(error) test_double.perform end it "should log that the database is being reconnected" do Rpush.logger.should_receive(:warn).with("Lost connection to database, reconnecting...") test_double.perform end it "should log the reconnection attempt" do Rpush.logger.should_receive(:warn).with("Attempt 1") test_double.perform end it "should clear all connections" do ActiveRecord::Base.should_receive(:clear_all_connections!) test_double.perform end it "should establish a new connection" do ActiveRecord::Base.should_receive(:establish_connection) test_double.perform end it "should test out the new connection by performing a count" do Rpush::Notification.should_receive(:count) test_double.perform end context "when the reconnection attempt is not successful" do before do class << Rpush::Notification def count @count_calls += 1 return if @count_calls == 2 raise @error end end Rpush::Notification.instance_variable_set("@count_calls", 0) Rpush::Notification.instance_variable_set("@error", error) end it "should log the 2nd attempt" do Rpush.logger.should_receive(:warn).with("Attempt 2") test_double.perform end it "should log errors raised when the reconnection is not successful" do Rpush.logger.should_receive(:error).with(error) test_double.perform end it "should sleep to avoid thrashing when the database is down" do test_double.should_receive(:sleep).with(2) test_double.perform end end end