bulk_operations 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +77 -0
- data/Rakefile +9 -0
- data/benchmark/main.rb +118 -0
- data/bulk_operations.gemspec +23 -0
- data/lib/bulk_operations.rb +17 -0
- data/lib/bulk_operations/ordered_bulk.rb +31 -0
- data/lib/bulk_operations/proxy.rb +33 -0
- data/lib/bulk_operations/struct_result.rb +24 -0
- data/lib/bulk_operations/unordered_bulk.rb +31 -0
- data/lib/bulk_operations/version.rb +3 -0
- data/spec/module_methods_spec.rb +12 -0
- data/spec/ordered_bulk_spec.rb +79 -0
- data/spec/proxied_object.rb +13 -0
- data/spec/proxy_spec.rb +79 -0
- data/spec/spec_helper.rb +11 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5a37693a3df12e721c5a22d877a255e208d4a660
|
4
|
+
data.tar.gz: af561b97f29cc392e802ff410e952f79dc41cbf7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 413659d4f53217baca7341fbde19c3a6727d29bf932c233f20078dd56f2d0b97bf011545f832a3ecbceb940767a092fa3b284c479a418b0d7a407492ec1aec13
|
7
|
+
data.tar.gz: 98d6c793c074b0bd205c45fe84f9b1e8f2ea45c5306a05c2a8789b8ea106f00bdc57ecabc8581b520f7e104f8300f5d2ed9affce756dd71b48d237fda82b6fa5
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
bulk_operations
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.2
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Jorge Luis Pérez
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# BulkOperations
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/jolisper/bulk_operations.svg?branch=master)](https://travis-ci.org/jolisper/bulk_operations)
|
4
|
+
|
5
|
+
Run your objects methods in a multi-threaded and bulked way.
|
6
|
+
|
7
|
+
## Motivation
|
8
|
+
You want to define different operations in a single object and you want to run them as a bulk and in a unordered (asynchronous) way. Also, you want to run them as a sequence, in the same order you called them.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'bulk_operations'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install bulk_operations
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
First define the class of your object:
|
27
|
+
```ruby
|
28
|
+
class MyObject
|
29
|
+
def operation_1
|
30
|
+
# operation_1 code goes here
|
31
|
+
end
|
32
|
+
|
33
|
+
def operation_2
|
34
|
+
# operation_2 code goes here
|
35
|
+
end
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
Then wrap your object in a bulk:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
require 'bulk_operations'
|
43
|
+
|
44
|
+
bulk = BulkOperations.unordered_bulk( MyObject.new )
|
45
|
+
```
|
46
|
+
|
47
|
+
Call your methods object through the bulk:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
bulk.operation_1
|
51
|
+
bulk.operation_2
|
52
|
+
```
|
53
|
+
|
54
|
+
The methods doesn't run immediately, you need to execute the bulk to run them:
|
55
|
+
```ruby
|
56
|
+
operations = bulk.execute
|
57
|
+
```
|
58
|
+
|
59
|
+
Through the `operations` object you can ask if a particular operation finished OK, and get the result of this operation:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
operations.operation_1.ok #=> returns true or false
|
63
|
+
operations.operation_1.result #=> returns the result or the raised exception
|
64
|
+
```
|
65
|
+
|
66
|
+
## Considerations about shared mutable state
|
67
|
+
|
68
|
+
Bulks doesn't care about the shared mutable state between your operations (at least in this version). So, if your operations share mutable state and you are using an unordered bulk, please add the necessary locks.
|
69
|
+
|
70
|
+
## Contributing
|
71
|
+
|
72
|
+
1. Fork it
|
73
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
74
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
75
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
76
|
+
5. Create new Pull Request
|
77
|
+
|
data/Rakefile
ADDED
data/benchmark/main.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
2
|
+
|
3
|
+
require 'bulk_operations'
|
4
|
+
require 'benchmark'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
class MyOperations
|
8
|
+
def yaml_to_object(yaml)
|
9
|
+
YAML.load(yaml)
|
10
|
+
end
|
11
|
+
|
12
|
+
def object_to_yaml(object)
|
13
|
+
object.to_yaml
|
14
|
+
end
|
15
|
+
|
16
|
+
def yaml_to_object2(yaml)
|
17
|
+
YAML.load(yaml)
|
18
|
+
end
|
19
|
+
|
20
|
+
def object_to_yaml2(object)
|
21
|
+
object.to_yaml
|
22
|
+
end
|
23
|
+
|
24
|
+
def yaml_to_object3(yaml)
|
25
|
+
YAML.load(yaml)
|
26
|
+
end
|
27
|
+
|
28
|
+
def object_to_yaml3(object)
|
29
|
+
object.to_yaml
|
30
|
+
end
|
31
|
+
|
32
|
+
def yaml_to_object4(yaml)
|
33
|
+
YAML.load(yaml)
|
34
|
+
end
|
35
|
+
|
36
|
+
def object_to_yaml4(object)
|
37
|
+
object.to_yaml
|
38
|
+
end
|
39
|
+
|
40
|
+
def yaml_to_object5(yaml)
|
41
|
+
YAML.load(yaml)
|
42
|
+
end
|
43
|
+
|
44
|
+
def object_to_yaml5(object)
|
45
|
+
object.to_yaml
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
class MyObject
|
51
|
+
attr_accessor :attr1, :attr2, :attr3
|
52
|
+
|
53
|
+
def initialize(attr1=1, attr2=2, attr3=3)
|
54
|
+
@attr1 = attr1
|
55
|
+
@attr2 = attr2
|
56
|
+
@attr3 = attr3
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
## Ordered Bulk
|
61
|
+
my_object = MyObject.new
|
62
|
+
|
63
|
+
ordered_bulk = BulkOperations.ordered_bulk(MyOperations.new)
|
64
|
+
|
65
|
+
ordered_bulk.yaml_to_object(my_object.to_yaml)
|
66
|
+
ordered_bulk.object_to_yaml(my_object)
|
67
|
+
ordered_bulk.yaml_to_object2(my_object.to_yaml)
|
68
|
+
ordered_bulk.object_to_yaml2(my_object)
|
69
|
+
ordered_bulk.yaml_to_object3(my_object.to_yaml)
|
70
|
+
ordered_bulk.object_to_yaml3(my_object)
|
71
|
+
ordered_bulk.yaml_to_object4(my_object.to_yaml)
|
72
|
+
ordered_bulk.object_to_yaml4(my_object)
|
73
|
+
ordered_bulk.yaml_to_object5(my_object.to_yaml)
|
74
|
+
ordered_bulk.object_to_yaml5(my_object)
|
75
|
+
|
76
|
+
## Unordered Bulk
|
77
|
+
my_object = MyObject.new
|
78
|
+
|
79
|
+
unordered_bulk = BulkOperations.unordered_bulk(MyOperations.new)
|
80
|
+
|
81
|
+
unordered_bulk.yaml_to_object(my_object.to_yaml)
|
82
|
+
unordered_bulk.object_to_yaml(my_object)
|
83
|
+
unordered_bulk.yaml_to_object2(my_object.to_yaml)
|
84
|
+
unordered_bulk.object_to_yaml2(my_object)
|
85
|
+
unordered_bulk.yaml_to_object3(my_object.to_yaml)
|
86
|
+
unordered_bulk.object_to_yaml3(my_object)
|
87
|
+
unordered_bulk.yaml_to_object4(my_object.to_yaml)
|
88
|
+
unordered_bulk.object_to_yaml4(my_object)
|
89
|
+
ordered_bulk.yaml_to_object5(my_object.to_yaml)
|
90
|
+
ordered_bulk.object_to_yaml5(my_object)
|
91
|
+
|
92
|
+
bench_mark = Proc.new do |cant_objects|
|
93
|
+
puts "----------------------------------------"
|
94
|
+
puts "Marshall/Unmarshall #{cant_objects} objects\n\n"
|
95
|
+
|
96
|
+
Benchmark.bm(15) do |b|
|
97
|
+
b.report("Ordered Bulk") do
|
98
|
+
cant_objects.times { ordered_bulk.execute }
|
99
|
+
end
|
100
|
+
|
101
|
+
b.report("Unordered Bulk") do
|
102
|
+
cant_objects.times { unordered_bulk.execute }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
puts "----------------------------------------\n"
|
107
|
+
end
|
108
|
+
|
109
|
+
# Rehersal
|
110
|
+
bench_mark.call 1_000
|
111
|
+
|
112
|
+
|
113
|
+
## Benchmarks
|
114
|
+
5.times do |i|
|
115
|
+
bench_mark.call 1_000 * (i + 1)
|
116
|
+
end
|
117
|
+
|
118
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bulk_operations/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "bulk_operations"
|
8
|
+
spec.version = BulkOperations::VERSION
|
9
|
+
spec.authors = ["Jorge Luis Pérez"]
|
10
|
+
spec.email = ["jolisper@gmail.com"]
|
11
|
+
spec.description = %q{Run your objects methods in a multithreaded and bulked way}
|
12
|
+
spec.summary = %q{Motivation: you want to define different operations in a single object and you want to run them as a bulk and in a unordered (asynchronous) way. Also, you want to run them as a sequence, in the same order you called them.}
|
13
|
+
spec.homepage = "https://github.com/jolisper/bulk_operations"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "bulk_operations/version"
|
2
|
+
require "bulk_operations/proxy"
|
3
|
+
require "bulk_operations/ordered_bulk"
|
4
|
+
require "bulk_operations/unordered_bulk"
|
5
|
+
require "bulk_operations/struct_result"
|
6
|
+
|
7
|
+
module BulkOperations
|
8
|
+
|
9
|
+
def self.unordered_bulk(object)
|
10
|
+
UnorderedBulkProxy.new(object)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.ordered_bulk(object)
|
14
|
+
OrderedBulkProxy.new(object)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module BulkOperations
|
2
|
+
class OrderedBulkProxy < BulkProxy
|
3
|
+
def do_execute
|
4
|
+
result = Hash.new
|
5
|
+
fibers = []
|
6
|
+
|
7
|
+
@operation_stack.each do |operation|
|
8
|
+
name, *args, block = *operation
|
9
|
+
fibers << create_fiber(name, args, block, result)
|
10
|
+
end
|
11
|
+
|
12
|
+
fibers.each(&:resume)
|
13
|
+
|
14
|
+
StructResult.new result
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_fiber(name, args, block, result)
|
18
|
+
fiber = Fiber.new do
|
19
|
+
begin
|
20
|
+
call_result = @proxied_object.__send__(name, *args, &block)
|
21
|
+
result[name] = { ok: true, result: call_result }
|
22
|
+
rescue => exception
|
23
|
+
result[name] = { ok: false, result: exception }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
fiber
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module BulkOperations
|
2
|
+
|
3
|
+
class OperationStackEmptyError < StandardError; end
|
4
|
+
|
5
|
+
class BulkProxy
|
6
|
+
attr_reader :proxied_object
|
7
|
+
|
8
|
+
def initialize(object)
|
9
|
+
@proxied_object = object
|
10
|
+
@operation_stack = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(name, *args, &block)
|
14
|
+
@operation_stack << [name, *args, block]
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute
|
18
|
+
raise OperationStackEmptyError if @operation_stack.empty?
|
19
|
+
do_execute
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module BulkOperations
|
4
|
+
class StructResult < OpenStruct
|
5
|
+
def initialize(hash=nil)
|
6
|
+
@table = {}
|
7
|
+
@hash_table = {}
|
8
|
+
|
9
|
+
if hash
|
10
|
+
hash.each do |k,v|
|
11
|
+
@table[k.to_sym] = (v.is_a?(Hash) ? self.class.new(v) : v)
|
12
|
+
@hash_table[k.to_sym] = v
|
13
|
+
|
14
|
+
new_ostruct_member(k)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
@hash_table
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module BulkOperations
|
2
|
+
class UnorderedBulkProxy < BulkProxy
|
3
|
+
def do_execute
|
4
|
+
result = Hash.new
|
5
|
+
threads = []
|
6
|
+
|
7
|
+
@operation_stack.each do |operation|
|
8
|
+
name, *args, block = *operation
|
9
|
+
threads << spawn_thread(name, args, block, result)
|
10
|
+
end
|
11
|
+
|
12
|
+
threads.each(&:join)
|
13
|
+
|
14
|
+
StructResult.new result
|
15
|
+
end
|
16
|
+
|
17
|
+
def spawn_thread(name, args, block, result)
|
18
|
+
thread = Thread.new do
|
19
|
+
begin
|
20
|
+
call_result = @proxied_object.__send__(name, *args, &block)
|
21
|
+
result[name] = { ok: true, result: call_result }
|
22
|
+
rescue => exception
|
23
|
+
result[name] = { ok: false, result: exception }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
thread
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative './spec_helper.rb'
|
2
|
+
|
3
|
+
describe BulkOperations do
|
4
|
+
|
5
|
+
describe "::unorderedBulk(object)" do
|
6
|
+
it "returns a BulkOperations::UnorderedBulkProxy" do
|
7
|
+
proxy = BulkOperations.unordered_bulk(Object.new)
|
8
|
+
proxy.must_be_instance_of BulkOperations::UnorderedBulkProxy
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative './spec_helper.rb'
|
2
|
+
require_relative './proxied_object.rb'
|
3
|
+
|
4
|
+
describe BulkOperations::OrderedBulkProxy do
|
5
|
+
|
6
|
+
describe "#proxied_object" do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@bulked = ProxiedObject.new
|
10
|
+
@bulk = BulkOperations.ordered_bulk(@bulked)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "returns the proxied object" do
|
14
|
+
@bulk.instance_variable_get("@proxied_object").must_equal(@bulked)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "when a method is called on a bulk proxy" do
|
18
|
+
it "the method call is added to the stack" do
|
19
|
+
@bulk.test_method(:param) { :block }
|
20
|
+
call_stack = @bulk.instance_variable_get("@operation_stack")
|
21
|
+
call_stack.size.must_equal 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#execute" do
|
28
|
+
describe "when the method stack is empty" do
|
29
|
+
let(:bulk) { BulkOperations.ordered_bulk(Object.new) }
|
30
|
+
|
31
|
+
it "raise OperationStackEmptyError" do
|
32
|
+
lambda { bulk.execute }.must_raise BulkOperations::OperationStackEmptyError
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "when the stack is NOT empty" do
|
38
|
+
before do
|
39
|
+
@bulk = BulkOperations.ordered_bulk(ProxiedObject.new)
|
40
|
+
@bulk.operation_1
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns a hash with the results of operation executions" do
|
44
|
+
@bulk.execute.must_be_instance_of BulkOperations::StructResult
|
45
|
+
end
|
46
|
+
|
47
|
+
it "the result hash has for the operation has ok: = true" do
|
48
|
+
result = @bulk.execute
|
49
|
+
result.operation_1.ok.must_equal true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "the result hash has for the operation has ok: = true" do
|
53
|
+
result = @bulk.execute
|
54
|
+
result.operation_1.result.must_equal 2
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "when an operation raise an exception" do
|
60
|
+
before do
|
61
|
+
@bulk = BulkOperations.ordered_bulk(ProxiedObject.new)
|
62
|
+
@bulk.raise_exception
|
63
|
+
end
|
64
|
+
|
65
|
+
it "the result hash has for the operation has ok: = false" do
|
66
|
+
result = @bulk.execute
|
67
|
+
result.raise_exception.ok.must_equal false
|
68
|
+
end
|
69
|
+
|
70
|
+
it "the result hash has for the exception throwed" do
|
71
|
+
result = @bulk.execute
|
72
|
+
result.raise_exception.result.must_be_instance_of StandardError
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/spec/proxy_spec.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative './spec_helper.rb'
|
2
|
+
require_relative './proxied_object.rb'
|
3
|
+
|
4
|
+
describe BulkOperations::UnorderedBulkProxy do
|
5
|
+
|
6
|
+
describe "#proxied_object" do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@bulked = ProxiedObject.new
|
10
|
+
@bulk = BulkOperations.unordered_bulk(@bulked)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "returns the proxied object" do
|
14
|
+
@bulk.instance_variable_get("@proxied_object").must_equal(@bulked)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "when a method is called on a bulk proxy" do
|
18
|
+
it "the method call is added to the stack" do
|
19
|
+
@bulk.test_method(:param) { :block }
|
20
|
+
call_stack = @bulk.instance_variable_get("@operation_stack")
|
21
|
+
call_stack.size.must_equal 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#execute" do
|
28
|
+
describe "when the method stack is empty" do
|
29
|
+
let(:bulk) { BulkOperations.unordered_bulk(Object.new) }
|
30
|
+
|
31
|
+
it "raise OperationStackEmptyError" do
|
32
|
+
lambda { bulk.execute }.must_raise BulkOperations::OperationStackEmptyError
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "when the stack is NOT empty" do
|
38
|
+
before do
|
39
|
+
@bulk = BulkOperations.unordered_bulk(ProxiedObject.new)
|
40
|
+
@bulk.operation_1
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns a hash with the results of operation executions" do
|
44
|
+
@bulk.execute.must_be_instance_of BulkOperations::StructResult
|
45
|
+
end
|
46
|
+
|
47
|
+
it "the result hash has for the operation has ok: = true" do
|
48
|
+
result = @bulk.execute
|
49
|
+
result.operation_1.ok.must_equal true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "the result hash has for the operation has ok: = true" do
|
53
|
+
result = @bulk.execute
|
54
|
+
result.operation_1.result.must_equal 2
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "when an operation raise an exception" do
|
60
|
+
before do
|
61
|
+
@bulk = BulkOperations.unordered_bulk(ProxiedObject.new)
|
62
|
+
@bulk.raise_exception
|
63
|
+
end
|
64
|
+
|
65
|
+
it "the result hash has for the operation has ok: = false" do
|
66
|
+
result = @bulk.execute
|
67
|
+
result.raise_exception.ok.must_equal false
|
68
|
+
end
|
69
|
+
|
70
|
+
it "the result hash has for the exception throwed" do
|
71
|
+
result = @bulk.execute
|
72
|
+
result.raise_exception.result.must_be_instance_of StandardError
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bulk_operations
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jorge Luis Pérez
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Run your objects methods in a multithreaded and bulked way
|
42
|
+
email:
|
43
|
+
- jolisper@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- ".ruby-gemset"
|
50
|
+
- ".ruby-version"
|
51
|
+
- ".travis.yml"
|
52
|
+
- Gemfile
|
53
|
+
- LICENSE.txt
|
54
|
+
- README.md
|
55
|
+
- Rakefile
|
56
|
+
- benchmark/main.rb
|
57
|
+
- bulk_operations.gemspec
|
58
|
+
- lib/bulk_operations.rb
|
59
|
+
- lib/bulk_operations/ordered_bulk.rb
|
60
|
+
- lib/bulk_operations/proxy.rb
|
61
|
+
- lib/bulk_operations/struct_result.rb
|
62
|
+
- lib/bulk_operations/unordered_bulk.rb
|
63
|
+
- lib/bulk_operations/version.rb
|
64
|
+
- spec/module_methods_spec.rb
|
65
|
+
- spec/ordered_bulk_spec.rb
|
66
|
+
- spec/proxied_object.rb
|
67
|
+
- spec/proxy_spec.rb
|
68
|
+
- spec/spec_helper.rb
|
69
|
+
homepage: https://github.com/jolisper/bulk_operations
|
70
|
+
licenses:
|
71
|
+
- MIT
|
72
|
+
metadata: {}
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 2.2.2
|
90
|
+
signing_key:
|
91
|
+
specification_version: 4
|
92
|
+
summary: 'Motivation: you want to define different operations in a single object and
|
93
|
+
you want to run them as a bulk and in a unordered (asynchronous) way. Also, you
|
94
|
+
want to run them as a sequence, in the same order you called them.'
|
95
|
+
test_files:
|
96
|
+
- spec/module_methods_spec.rb
|
97
|
+
- spec/ordered_bulk_spec.rb
|
98
|
+
- spec/proxied_object.rb
|
99
|
+
- spec/proxy_spec.rb
|
100
|
+
- spec/spec_helper.rb
|