sunspot-rails-failover 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2@sunspot-rails-failover --create
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Justin Ko
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # sunspot-rails-failover
2
+
3
+ Sunspot comes with `MasterSlaveSessionProxy` that does the following:
4
+
5
+ > This session proxy implementation allows Sunspot to be used with a
6
+ > master/slave Solr deployment. All write methods are delegated to a master
7
+ > session, and read methods are delegated to a slave session.
8
+
9
+ What this simple gem does is provide failover support if the slave session
10
+ goes down. Reads *and* writes are called on the master session.
11
+
12
+ ## Setup
13
+
14
+ Your config/sunspot.yml file should look something like this:
15
+
16
+ development:
17
+ master_solr:
18
+ url: http://localhost:8984/solr
19
+ solr:
20
+ url: http://localhost:8985/solr
21
+
22
+ NOTE: You do *not* have to have a master session. If a master session is
23
+ not detected, sunspot-rails-failover will default to what sunspot_rails
24
+ provides.
25
+
26
+ Next, add an initializer (maybe initializers/sunspot.rb) with the following
27
+ code:
28
+
29
+ Sunspot::Rails::Failover.setup
30
+
31
+ ## Exception handling
32
+
33
+ sunspot-rails-failover supports exception handling for committing and
34
+ searching. Currently, it will use Hoptoad by default if it is installed.
35
+ The exception is passed to `HoptoadNotifier.notify`.
36
+
37
+ You can also use a custom class/module to customize how you want to handle the
38
+ exception. In `initializers/sunspot.rb`:
39
+
40
+ module MyExceptionHandler
41
+ def self.handle(exception)
42
+ Notifier.deliver_exception_message(exception)
43
+ end
44
+ end
45
+
46
+ Sunspot::Rails::Failover.exception_handler = MyExceptionHandler
47
+ Sunspot::Rails::Failover.setup
48
+
49
+ ## Copyright
50
+
51
+ Copyright (c) 2011 Justin Ko. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new
6
+
7
+ task :default => :spec
@@ -0,0 +1,39 @@
1
+ require 'sunspot'
2
+ require 'sunspot-rails-failover/master_slave_with_failover_session_proxy'
3
+ require 'sunspot-rails-failover/exception_handler_adapter'
4
+
5
+ module Sunspot
6
+ module Rails
7
+ module Failover
8
+ class << self
9
+ attr_accessor :exception_handler
10
+
11
+ def setup
12
+ Sunspot.session = if Sunspot::Rails.configuration.has_master?
13
+ Sunspot::SessionProxy::MasterSlaveWithFailoverSessionProxy.new(
14
+ Sunspot::Session.new(master_config), Sunspot::Session.new(slave_config)
15
+ )
16
+ else
17
+ Sunspot::SessionProxy::ThreadLocalSessionProxy.new(slave_config)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def slave_config
24
+ build_config('solr', 'url')
25
+ end
26
+
27
+ def master_config
28
+ build_config('master_solr', 'url')
29
+ end
30
+
31
+ def build_config(*keys)
32
+ Sunspot::Configuration.build.tap do |config|
33
+ config.solr.url = Sunspot::Rails.configuration.send :user_configuration_from_key, *keys
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,22 @@
1
+ module Sunspot
2
+ module Rails
3
+ module Failover
4
+ module ExceptionHandlerAdapter
5
+
6
+ def self.handle(exception)
7
+ case exception_handler
8
+ when :hoptoad, nil
9
+ HoptoadNotifier.notify(exception) if defined?(HoptoadNotifier)
10
+ when Class
11
+ exception_handler.handle(exception)
12
+ end
13
+ end
14
+
15
+ def self.exception_handler
16
+ Failover.exception_handler
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ module Sunspot
2
+ module SessionProxy
3
+ class MasterSlaveWithFailoverSessionProxy < MasterSlaveSessionProxy
4
+
5
+ attr_accessor :exception
6
+
7
+ def commit
8
+ with_exception_handling do
9
+ master_session.commit
10
+ end
11
+ end
12
+
13
+ def search(*types, &block)
14
+ [slave_session, master_session].any? do |session|
15
+ with_exception_handling { session.search(*types, &block) }
16
+ end or raise(exception)
17
+ end
18
+
19
+ private
20
+
21
+ def with_exception_handling
22
+ yield
23
+ rescue Exception => exception
24
+ Sunspot::Rails::Failover::ExceptionHandlerAdapter.handle(exception)
25
+ self.exception = exception
26
+ false
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,7 @@
1
+ module Sunspot
2
+ module Rails
3
+ module Failover
4
+ VERSION = "0.0.3"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+
5
+ require 'sunspot-rails-failover'
6
+
7
+ Dir['./spec/support/*.rb'].map {|f| require f }
8
+
9
+ RSpec.configure do |config|
10
+ config.color_enabled = true
11
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ require 'hoptoad_notifier'
4
+
5
+ shared_examples_for 'a hoptoad handler' do
6
+ it 'uses the api' do
7
+ HoptoadNotifier.should_receive(:notify).with(exception)
8
+ described_class.handle(exception)
9
+ end
10
+ end
11
+
12
+ describe Sunspot::Rails::Failover::ExceptionHandlerAdapter do
13
+ describe '.handle' do
14
+ let(:exception) { Exception.new }
15
+
16
+ context 'with exception_handler not set (default)' do
17
+ it_should_behave_like 'a hoptoad handler'
18
+ end
19
+
20
+ context 'with exception_handler set to :hoptoad' do
21
+ before { Sunspot::Rails::Failover.exception_handler = :hoptoad }
22
+ it_should_behave_like 'a hoptoad handler'
23
+ end
24
+
25
+ context 'with exception_handler set to a custom class' do
26
+ before { Sunspot::Rails::Failover.exception_handler = MyExceptionHandler }
27
+
28
+ it 'passes the exception to #handle' do
29
+ MyExceptionHandler.should_receive(:handle).with(exception)
30
+ described_class.handle(exception)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sunspot::SessionProxy::MasterSlaveWithFailoverSessionProxy do
4
+ let(:master) { Sunspot::Session.new }
5
+ let(:slave) { Sunspot::Session.new }
6
+ let(:proxy) { Sunspot::SessionProxy::MasterSlaveWithFailoverSessionProxy.new(master, slave) }
7
+
8
+ let(:exception_handler_adapter) { Sunspot::Rails::Failover::ExceptionHandlerAdapter }
9
+
10
+ describe '#commit' do
11
+ context 'with no error' do
12
+ it 'calls on the master session' do
13
+ master.should_receive(:commit)
14
+ proxy.commit
15
+ end
16
+ end
17
+
18
+ context 'with an error' do
19
+ it 'passes the exception to the exception handler adapter' do
20
+ exception = Exception.new
21
+ exception_handler_adapter.should_receive(:handle).with(exception)
22
+ master.should_receive(:commit).and_raise(exception)
23
+ proxy.commit
24
+ end
25
+ end
26
+ end
27
+
28
+ describe '#search' do
29
+ context 'with no error' do
30
+ it 'calls on the slave session' do
31
+ slave.should_receive(:search).and_return(true)
32
+ master.should_not_receive(:search)
33
+ proxy.search
34
+ end
35
+ end
36
+
37
+ context 'with an error on the slave session' do
38
+ it 'calls on the master session' do
39
+ exception = Exception.new
40
+ slave.should_receive(:search).and_raise(exception)
41
+ exception_handler_adapter.should_receive(:handle).with(exception)
42
+ master.should_receive(:search).and_return(true)
43
+ proxy.search
44
+ end
45
+ end
46
+
47
+ context 'with an error on the slave and master sessions' do
48
+ it 'raises the error with no handling' do
49
+ exception = Exception.new
50
+ slave.should_receive(:search).and_raise(exception)
51
+ master.should_receive(:search).and_raise(exception)
52
+ exception_handler_adapter.should_receive(:handle).with(exception).twice
53
+ proxy.should_receive(:raise).with(exception)
54
+ proxy.search
55
+ end
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sunspot::Rails::Failover do
4
+ describe '.setup' do
5
+ let(:configuration) { double('configuration') }
6
+
7
+ before do
8
+ Sunspot::Rails.stub(:configuration).and_return(configuration)
9
+ configuration.should_receive(:user_configuration_from_key).with('solr', 'url')
10
+ end
11
+
12
+ context 'with a master configuration' do
13
+ before do
14
+ configuration.should_receive(:has_master?).and_return(true)
15
+ configuration.should_receive(:user_configuration_from_key).with('master_solr', 'url')
16
+ end
17
+
18
+ it 'sets the session to master/slave with failover support' do
19
+ described_class.setup
20
+ Sunspot.session.should be_an_instance_of(Sunspot::SessionProxy::MasterSlaveWithFailoverSessionProxy)
21
+ end
22
+ end
23
+
24
+ context 'with no master configuration' do
25
+ before do
26
+ configuration.should_receive(:has_master?).and_return(false)
27
+ end
28
+
29
+ it 'sets the session to the default' do
30
+ described_class.setup
31
+ Sunspot.session.should be_an_instance_of(Sunspot::SessionProxy::ThreadLocalSessionProxy)
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,4 @@
1
+ class MyExceptionHandler
2
+ def handle
3
+ end
4
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'sunspot-rails-failover/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'sunspot-rails-failover'
7
+ s.version = Sunspot::Rails::Failover::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.author = 'Justin Ko'
10
+ s.email = 'jko170@gmail.com'
11
+ s.homepage = 'https://github.com/justinko/sunspot-rails-failover'
12
+ s.description = 'Failover support for sunspot_rails'
13
+ s.summary = 'If the Sunspot slave session goes down, reads *and* writes ' \
14
+ 'are called upon the master session'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- spec/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_path = 'lib'
20
+
21
+ s.add_dependency 'sunspot_rails', '~> 1.2.1'
22
+
23
+ s.add_development_dependency 'rspec', '~> 2.5'
24
+ s.add_development_dependency 'hoptoad_notifier'
25
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: sunspot-rails-failover
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.2
5
+ version: 0.0.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Justin Ko
@@ -54,8 +54,23 @@ extensions: []
54
54
 
55
55
  extra_rdoc_files: []
56
56
 
57
- files: []
58
-
57
+ files:
58
+ - .gitignore
59
+ - .rvmrc
60
+ - Gemfile
61
+ - LICENSE
62
+ - README.md
63
+ - Rakefile
64
+ - lib/sunspot-rails-failover.rb
65
+ - lib/sunspot-rails-failover/exception_handler_adapter.rb
66
+ - lib/sunspot-rails-failover/master_slave_with_failover_session_proxy.rb
67
+ - lib/sunspot-rails-failover/version.rb
68
+ - spec/spec_helper.rb
69
+ - spec/sunspot-rails-failover/exception_handler_adapter_spec.rb
70
+ - spec/sunspot-rails-failover/master_slave_with_failover_session_proxy_spec.rb
71
+ - spec/sunspot-rails-failover_spec.rb
72
+ - spec/support/my_exception_handler.rb
73
+ - sunspot-rails-failover.gemspec
59
74
  has_rdoc: true
60
75
  homepage: https://github.com/justinko/sunspot-rails-failover
61
76
  licenses: []
@@ -83,6 +98,10 @@ rubyforge_project:
83
98
  rubygems_version: 1.6.2
84
99
  signing_key:
85
100
  specification_version: 3
86
- summary: Failover support for sunspot_rails
87
- test_files: []
88
-
101
+ summary: If the Sunspot slave session goes down, reads *and* writes are called upon the master session
102
+ test_files:
103
+ - spec/spec_helper.rb
104
+ - spec/sunspot-rails-failover/exception_handler_adapter_spec.rb
105
+ - spec/sunspot-rails-failover/master_slave_with_failover_session_proxy_spec.rb
106
+ - spec/sunspot-rails-failover_spec.rb
107
+ - spec/support/my_exception_handler.rb