Navigation Menu

Skip to content
This repository has been archived by the owner on Jul 4, 2022. It is now read-only.

Commit

Permalink
Added the batcher class.
Browse files Browse the repository at this point in the history
  • Loading branch information
thhermansen authored and alindeman committed Jan 28, 2012
1 parent 48c40a9 commit 49dfd4f
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 0 deletions.
76 changes: 76 additions & 0 deletions sunspot/lib/sunspot/batcher.rb
@@ -0,0 +1,76 @@
module Sunspot

#
# Keeps a stack of batches and helps out when Indexer is asked to batch documents.
#
# If the client does something like
#
# Sunspot.batch do
# some_code_here
# which_triggers_some_other_code
# which_again_calls
# Sunspot.batch { ... }
# end
#
# it is the Batcher's job to keep track of these nestings. The inner will
# be sent of to be indexed first.
#
class Batcher
include Enumerable

# Raised if you ask to end current, but no current exists
class NoCurrentBatchError < StandardError; end


def initialize
@stack = []
end



def current
stack.last or start_new
end

def start_new
(stack << []).last
end

def end_current
fail NoCurrentBatchError if stack.empty?

stack.pop
end



def depth
stack.length
end

def batching?
depth > 0
end



def each
current.each { |v| yield v }
end

def push(value)
current << value
end
alias << push

def concat(values)
current.concat values
end



private

attr_reader :stack
end
end
2 changes: 2 additions & 0 deletions sunspot/lib/sunspot/indexer.rb
@@ -1,3 +1,5 @@
require 'sunspot/batcher'

module Sunspot
#
# This class presents a service for adding, updating, and removing data
Expand Down
112 changes: 112 additions & 0 deletions sunspot/spec/api/batcher_spec.rb
@@ -0,0 +1,112 @@
require File.expand_path('spec_helper', File.dirname(__FILE__))

describe Sunspot::Batcher do
it "includes Enumerable" do
described_class.should include Enumerable
end

describe "#each" do
let(:current) { [:foo, :bar] }
before { subject.stub(:current).and_return current }

it "iterates over current" do
yielded_values = []

subject.each do |value|
yielded_values << value
end

yielded_values.should eq current
end
end

describe "adding to current batch" do
it "#push pushes to current" do
subject.push :foo
subject.current.should include :foo
end

it "#<< pushes to current" do
subject.push :foo
subject.current.should include :foo
end

it "#concat concatinates on current batch" do
subject << :foo
subject.concat [:bar, :mix]
should include :foo, :bar, :mix
end
end


describe "#current" do
context "no current" do
it "starts a new" do
expect { subject.current }.to change(subject, :depth).by 1
end

it "is empty by default" do
subject.current.should be_empty
end
end

context "with a current" do
before { subject.start_new }

it "does not start a new" do
expect { subject.current }.to_not change(subject, :depth)
end

it "returns the same as last time" do
subject.current.should eq subject.current
end
end
end

describe "#start_new" do
it "creates a new batches" do
expect { 2.times { subject.start_new } }.to change(subject, :depth).by 2
end

it "changes current" do
subject << :foo
subject.start_new
should_not include :foo
end
end

describe "#end_current" do
context "no current batch" do
it "fails" do
expect { subject.end_current }.to raise_error Sunspot::Batcher::NoCurrentBatchError
end
end

context "with current batch" do
before { subject.start_new }

it "changes current" do
subject << :foo
subject.end_current
should_not include :foo
end

it "returns current" do
subject << :foo
subject.end_current.should include :foo
end
end
end

describe "#batching?" do
it "is false when depth is 0" do
subject.should_receive(:depth).and_return 0
should_not be_batching
end

it "is true when depth is more than 0" do
subject.should_receive(:depth).and_return 1
should be_batching
end
end
end

0 comments on commit 49dfd4f

Please sign in to comment.