batchr 0.1.0
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 +4 -0
- data/.rvmrc +7 -0
- data/Gemfile +3 -0
- data/README.md +41 -0
- data/Rakefile +1 -0
- data/batchr.gemspec +20 -0
- data/lib/batchr.rb +45 -0
- data/lib/batchr/version.rb +3 -0
- data/spec/batchr_spec.rb +132 -0
- metadata +73 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# if you're using system, let's use 1.9.2. Otherwise, leave the ruby alone
|
2
|
+
[[ `rvm tools identifier` == 'system' ]] && rvm use 1.9.2
|
3
|
+
|
4
|
+
# create idkfa gemset if necessary
|
5
|
+
(rvm gemset list | grep batchr &> /dev/null) || rvm gemset create batchr
|
6
|
+
|
7
|
+
rvm gemset use batchr
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
Batchr
|
2
|
+
======
|
3
|
+
|
4
|
+
Installation
|
5
|
+
------------
|
6
|
+
|
7
|
+
### With Bundler
|
8
|
+
|
9
|
+
gem 'batchr'
|
10
|
+
|
11
|
+
### With Only Rubygems
|
12
|
+
|
13
|
+
$ gem install batchr
|
14
|
+
|
15
|
+
Usage
|
16
|
+
-----
|
17
|
+
|
18
|
+
class Receiver
|
19
|
+
def self.message objects = []
|
20
|
+
# your code do deal with a "batch" of objects
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Batchr.batch(Receiver, :message) do |batchr|
|
25
|
+
# batchr.batch_size = 400 (default)
|
26
|
+
1_000_000.times do
|
27
|
+
batchr << rand
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Contributing
|
32
|
+
------------
|
33
|
+
|
34
|
+
Want to contribute? Great!
|
35
|
+
|
36
|
+
1. Fork it.
|
37
|
+
1. Create a branch (git checkout -b my_feature).
|
38
|
+
1. Commit your changes (git commit -am "Added Awesomeness").
|
39
|
+
1. Push to the branch (git push origin my_feature).
|
40
|
+
1. Create an Issue with a link to your branch.
|
41
|
+
1. Enjoy a refreshing beverage of your choice and wait.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/batchr.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "batchr/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "batchr"
|
7
|
+
s.version = Batchr::VERSION
|
8
|
+
s.authors = ["Bradley Grzesiak"]
|
9
|
+
s.email = ["brad@bendyworks.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Batching library for ruby}
|
12
|
+
s.description = %q{Perfect for batching operations over long enumerables}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
16
|
+
s.executables = [] # `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_development_dependency "rspec"
|
20
|
+
end
|
data/lib/batchr.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
class Batchr
|
2
|
+
|
3
|
+
attr_reader :batch_size, :bucket
|
4
|
+
attr_accessor :receiver, :message
|
5
|
+
|
6
|
+
def self.batch receiver, message
|
7
|
+
batchr = new
|
8
|
+
batchr.receiver = receiver
|
9
|
+
batchr.message = message
|
10
|
+
yield batchr
|
11
|
+
batchr.finish
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize opts = {}
|
15
|
+
@batch_size = opts[:batch_size] ? opts[:batch_size] : 400
|
16
|
+
@bucket = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def batch_size= value
|
20
|
+
@batch_size = value
|
21
|
+
run_if_necessary
|
22
|
+
end
|
23
|
+
|
24
|
+
def << value
|
25
|
+
@bucket << value
|
26
|
+
run_if_necessary
|
27
|
+
end
|
28
|
+
|
29
|
+
def run_if_necessary
|
30
|
+
run_batch if @bucket.size >= @batch_size
|
31
|
+
end
|
32
|
+
|
33
|
+
def empty_bucket
|
34
|
+
@bucket = []
|
35
|
+
end
|
36
|
+
|
37
|
+
def run_batch
|
38
|
+
unless bucket.empty?
|
39
|
+
receiver.send(message, bucket)
|
40
|
+
empty_bucket
|
41
|
+
end
|
42
|
+
end
|
43
|
+
alias_method :finish, :run_batch
|
44
|
+
|
45
|
+
end
|
data/spec/batchr_spec.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require_relative '../lib/batchr'
|
3
|
+
|
4
|
+
class Receiver
|
5
|
+
def self.message batch
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Batchr do
|
10
|
+
describe '.batch' do
|
11
|
+
|
12
|
+
it 'yields an instance of Batchr' do
|
13
|
+
Batchr.batch(Receiver, :message) do |b|
|
14
|
+
b.stub(:finish)
|
15
|
+
b.should be_a(Batchr)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'calls finish at the end of the block' do
|
20
|
+
Batchr.batch(Receiver, :message) do |b|
|
21
|
+
b.should_receive(:finish)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#initialize' do
|
28
|
+
context 'with batch_size opt' do
|
29
|
+
it 'sets the batch_size' do
|
30
|
+
Batchr.new(batch_size: 3).batch_size.should == 3
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#batch_size=' do
|
36
|
+
let(:batchr) { Batchr.new }
|
37
|
+
it 'sets the batch size' do
|
38
|
+
batchr.stub(:run_if_necessary)
|
39
|
+
batchr.batch_size = 2
|
40
|
+
batchr.batch_size.should == 2
|
41
|
+
end
|
42
|
+
it 'calls run_if_necessary' do
|
43
|
+
batchr.should_receive(:run_if_necessary).once
|
44
|
+
batchr.batch_size = 2
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#<<' do
|
49
|
+
let(:batchr) { Batchr.new }
|
50
|
+
it 'adds the element to the bucket' do
|
51
|
+
batchr << :a
|
52
|
+
batchr.bucket.should == [:a]
|
53
|
+
end
|
54
|
+
it 'calls run_if_necessary' do
|
55
|
+
batchr.should_receive(:run_if_necessary)
|
56
|
+
batchr << :foo
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#run_if_necessary' do
|
61
|
+
let(:batchr) { Batchr.new(batch_size: 1) }
|
62
|
+
after { batchr.run_if_necessary }
|
63
|
+
|
64
|
+
context 'buffered size is greater than batch_size' do
|
65
|
+
it 'calls run_batch' do
|
66
|
+
batchr.should_receive(:run_batch)
|
67
|
+
batchr.instance_variable_set("@bucket", [:foo, :bar])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'buffered size is equal to batch_size' do
|
72
|
+
it 'calls run_batch' do
|
73
|
+
batchr.should_receive(:run_batch)
|
74
|
+
batchr.instance_variable_set("@bucket", [:foo])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'buffered size is less than batch_size' do
|
79
|
+
it 'does not call run_batch' do
|
80
|
+
batchr.should_not_receive(:run_batch)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#run_batch' do
|
87
|
+
let(:batchr) { Batchr.new }
|
88
|
+
before do
|
89
|
+
batchr.receiver, batchr.message = Receiver, :message
|
90
|
+
batchr.bucket.stub(empty?: empty_bucket)
|
91
|
+
end
|
92
|
+
context 'when bucket has something' do
|
93
|
+
let(:empty_bucket) { false }
|
94
|
+
it 'calls message on reciever with the bucket as an arg' do
|
95
|
+
Receiver.should_receive(:message).with(batchr.bucket)
|
96
|
+
batchr.run_batch
|
97
|
+
end
|
98
|
+
it 'empties the bucket' do
|
99
|
+
batchr.run_batch
|
100
|
+
batchr.bucket.should == []
|
101
|
+
end
|
102
|
+
end
|
103
|
+
context 'when bucket is empty' do
|
104
|
+
let(:empty_bucket) { true }
|
105
|
+
it 'does not call message on receiver' do
|
106
|
+
Receiver.should_not_receive(:message)
|
107
|
+
batchr.run_batch
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
example 'batch_size = 2, elements = 2' do
|
113
|
+
Receiver.should_receive(:message).with([:a, :b]).once
|
114
|
+
Batchr.batch(Receiver, :message) do |batchr|
|
115
|
+
batchr.batch_size = 2
|
116
|
+
batchr << :a
|
117
|
+
batchr << :b
|
118
|
+
batchr.bucket.should == []
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
example 'batch_size = 3, elements = 2' do
|
123
|
+
Receiver.should_receive(:message).with([:a, :b]).once
|
124
|
+
Batchr.batch(Receiver, :message) do |batchr|
|
125
|
+
batchr.batch_size = 3
|
126
|
+
batchr << :a
|
127
|
+
batchr << :b
|
128
|
+
batchr.bucket.should == [:a, :b]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: batchr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Bradley Grzesiak
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-10-28 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :development
|
25
|
+
version_requirements: *id001
|
26
|
+
description: Perfect for batching operations over long enumerables
|
27
|
+
email:
|
28
|
+
- brad@bendyworks.com
|
29
|
+
executables: []
|
30
|
+
|
31
|
+
extensions: []
|
32
|
+
|
33
|
+
extra_rdoc_files: []
|
34
|
+
|
35
|
+
files:
|
36
|
+
- .gitignore
|
37
|
+
- .rvmrc
|
38
|
+
- Gemfile
|
39
|
+
- README.md
|
40
|
+
- Rakefile
|
41
|
+
- batchr.gemspec
|
42
|
+
- lib/batchr.rb
|
43
|
+
- lib/batchr/version.rb
|
44
|
+
- spec/batchr_spec.rb
|
45
|
+
homepage: ""
|
46
|
+
licenses: []
|
47
|
+
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: "0"
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.8.3
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: Batching library for ruby
|
72
|
+
test_files:
|
73
|
+
- spec/batchr_spec.rb
|