sunspot-rails-failover 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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