up_and_at_them 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.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/README.md +10 -4
- data/lib/up_and_at_them/commit.rb +24 -0
- data/lib/up_and_at_them/transaction.rb +25 -0
- data/lib/up_and_at_them/version.rb +1 -1
- data/lib/up_and_at_them.rb +3 -47
- data/spec/spec_helper.rb +9 -0
- data/spec/transaction_spec.rb +80 -0
- data/up_and_at_them.gemspec +2 -0
- metadata +24 -5
- data/test/test_transaction.rb +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 939048fd2ad08daec7378c1b4dd93c5fc2416e80
|
4
|
+
data.tar.gz: 5065388003473404532a5e72fe4951eae85c911a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21660a484924d390ab20a6f11b7e678f46efc69cd9cdd1a7380e965c5c22e449dc673e01e32971d629526be7e3e14e2ea8a90b47df2c1e6cff6b857b1eab15c9
|
7
|
+
data.tar.gz: 0bd1b751dece6ce750eb5fd0fdfd84ed4287a53f0be8c8c54fed976328fec46988272a8a60d39aed3e5c577976361f458b10adbfd036efcaf6f820e0ce15fbe7
|
data/.rspec
ADDED
data/README.md
CHANGED
@@ -25,10 +25,16 @@ Or install it yourself as:
|
|
25
25
|
Create a Transaction which contains all of your commits. Note that the Transaction will run as soon as it is
|
26
26
|
initialized.
|
27
27
|
|
28
|
-
UpAndAtThem::Transaction
|
29
|
-
|
30
|
-
|
31
|
-
]
|
28
|
+
UpAndAtThem::Transaction[
|
29
|
+
UpAndAtThem::Commit.new { puts "do something!" }.on_rollback { "undo something!" },
|
30
|
+
UpAndAtThem::Commit.new { puts "do something else!" }.on_rollback { "undo something else!" }
|
31
|
+
]
|
32
|
+
|
33
|
+
The `UpAndAtThem::Transaction` array can contain any classes that respond to `#call` and `#rollback`. The
|
34
|
+
`UpAndAtThem::Commit` class allows you to define those methods easily:
|
35
|
+
|
36
|
+
UpAndAtThem::Commit.new { "this block will execute on #call" }.on_rollback { "this block will execute on #rollback" }
|
37
|
+
UpAndAtThem::Commit.new { "calling on_rollback is not necessary" }
|
32
38
|
|
33
39
|
See the tests for other example Commit actions within a Transaction.
|
34
40
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module UpAndAtThem
|
2
|
+
class Commit
|
3
|
+
|
4
|
+
def initialize(&block)
|
5
|
+
raise LocalJumpError unless block_given?
|
6
|
+
@block = block
|
7
|
+
end
|
8
|
+
|
9
|
+
def on_rollback(&block)
|
10
|
+
raise LocalJumpError unless block_given?
|
11
|
+
@rollback = block
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
@block.call
|
17
|
+
end
|
18
|
+
|
19
|
+
def rollback
|
20
|
+
@rollback.call if @rollback
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module UpAndAtThem
|
2
|
+
class Transaction
|
3
|
+
|
4
|
+
def self.[](*tasks)
|
5
|
+
new(tasks)
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(tasks)
|
9
|
+
@tasks = Array(tasks)
|
10
|
+
run
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
finished_tasks = []
|
15
|
+
@tasks.each do |task|
|
16
|
+
task.call
|
17
|
+
finished_tasks << task
|
18
|
+
end
|
19
|
+
rescue => err
|
20
|
+
finished_tasks.reverse_each(&:rollback)
|
21
|
+
raise err
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/up_and_at_them.rb
CHANGED
@@ -1,47 +1,3 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
|
4
|
-
class Commit
|
5
|
-
def initialize(&block)
|
6
|
-
raise LocalJumpError unless block_given?
|
7
|
-
@block = block
|
8
|
-
end
|
9
|
-
def on_rollback(&block)
|
10
|
-
raise LocalJumpError unless block_given?
|
11
|
-
@rollback = block
|
12
|
-
self
|
13
|
-
end
|
14
|
-
def call
|
15
|
-
@block.call
|
16
|
-
end
|
17
|
-
def rollback
|
18
|
-
@rollback.call if @rollback
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class Transaction
|
23
|
-
def initialize(tasks)
|
24
|
-
tasks = Array(tasks)
|
25
|
-
tasks.each do |t|
|
26
|
-
Commit === t or raise TypeError
|
27
|
-
end
|
28
|
-
@tasks = tasks
|
29
|
-
run
|
30
|
-
end
|
31
|
-
|
32
|
-
def run
|
33
|
-
finished_tasks = []
|
34
|
-
begin
|
35
|
-
@tasks.each do |task|
|
36
|
-
task.call
|
37
|
-
finished_tasks << task
|
38
|
-
end
|
39
|
-
rescue => err
|
40
|
-
finished_tasks.reverse_each do |task|
|
41
|
-
task.rollback
|
42
|
-
end
|
43
|
-
raise err
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
1
|
+
require 'up_and_at_them/version'
|
2
|
+
require 'up_and_at_them/commit'
|
3
|
+
require 'up_and_at_them/transaction'
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
describe UpAndAtThem::Transaction do
|
2
|
+
|
3
|
+
it 'rolls back past commits' do
|
4
|
+
flags = { 1 => :pending, 2 => :pending, 3 => :pending, 4 => :pending }
|
5
|
+
commits = (1...4).map do |i|
|
6
|
+
UpAndAtThem::Commit.new { flags[i] = :committed; if i==3 ; raise 'uh oh!'; end }.on_rollback { flags[i] = :rolled_back }
|
7
|
+
end
|
8
|
+
expect { UpAndAtThem::Transaction.new commits }.to raise_error(RuntimeError)
|
9
|
+
expect(flags[1]).to eq :rolled_back
|
10
|
+
expect(flags[4]).to eq :pending
|
11
|
+
expect(flags[3]).to eq :committed
|
12
|
+
expect(flags[2]).to eq :rolled_back
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'rolls back in reverse commit order' do
|
16
|
+
flags = { 1 => -1, 2 => -1, 3 => -1, 4 => -1 }
|
17
|
+
commits = (1...4).map do |i|
|
18
|
+
UpAndAtThem::Commit.new { flags[i] = -1; if i==3 ; raise 'uh oh!'; end }.on_rollback { flags[i] = Time.now; sleep 1 }
|
19
|
+
end
|
20
|
+
expect { UpAndAtThem::Transaction.new commits }.to raise_error(RuntimeError)
|
21
|
+
expect(flags[4].to_f).to eq -1
|
22
|
+
expect(flags[3].to_f).to be < flags[2].to_f
|
23
|
+
expect(flags[2].to_f).to be < flags[1].to_f
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'allows no-rollback commits' do
|
27
|
+
flags = {1 => :pending, 2 => :pending, 3 => :pending, 4 => :pending}
|
28
|
+
commits = (1...4).map do |i|
|
29
|
+
UpAndAtThem::Commit.new { flags[i] = :committed; if i==3 ; raise 'fail!'; end }
|
30
|
+
end
|
31
|
+
expect { UpAndAtThem::Transaction.new commits }.to raise_error(RuntimeError)
|
32
|
+
expect(flags[4]).to eq :pending
|
33
|
+
expect(flags[3]).to eq :committed
|
34
|
+
expect(flags[2]).to eq :committed
|
35
|
+
expect(flags[1]).to eq :committed
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '.[]' do
|
39
|
+
it 'instantiates a new Transaction' do
|
40
|
+
commit = -> { raise 'fail!' }
|
41
|
+
expect { UpAndAtThem::Transaction[commit] }.to raise_error(RuntimeError)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'duck typed Commits' do
|
46
|
+
class TestCommit
|
47
|
+
attr_reader :state
|
48
|
+
|
49
|
+
def initialize(fail = false)
|
50
|
+
@fail = fail
|
51
|
+
@state = :pending
|
52
|
+
end
|
53
|
+
|
54
|
+
def call
|
55
|
+
@state = :committed
|
56
|
+
raise if @fail
|
57
|
+
end
|
58
|
+
|
59
|
+
def rollback
|
60
|
+
@state = :rolled_back
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'runs #call on each commit' do
|
65
|
+
commit = TestCommit.new
|
66
|
+
UpAndAtThem::Transaction[commit]
|
67
|
+
expect(commit.state).to eq :committed
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'runs #rollback when the commit fails' do
|
71
|
+
commit1 = TestCommit.new
|
72
|
+
commit2 = TestCommit.new(true)
|
73
|
+
expect { UpAndAtThem::Transaction[commit1, commit2] }.to raise_error
|
74
|
+
expect(commit1.state).to eq :rolled_back
|
75
|
+
expect(commit2.state).to eq :committed
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/up_and_at_them.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: up_and_at_them
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dave Lane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
description: A library for simplifying atomic transactions with the option for rollback
|
42
56
|
of each operation in the transaction.
|
43
57
|
email:
|
@@ -47,13 +61,17 @@ extensions: []
|
|
47
61
|
extra_rdoc_files: []
|
48
62
|
files:
|
49
63
|
- ".gitignore"
|
64
|
+
- ".rspec"
|
50
65
|
- Gemfile
|
51
66
|
- LICENSE.txt
|
52
67
|
- README.md
|
53
68
|
- Rakefile
|
54
69
|
- lib/up_and_at_them.rb
|
70
|
+
- lib/up_and_at_them/commit.rb
|
71
|
+
- lib/up_and_at_them/transaction.rb
|
55
72
|
- lib/up_and_at_them/version.rb
|
56
|
-
-
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
- spec/transaction_spec.rb
|
57
75
|
- up_and_at_them.gemspec
|
58
76
|
homepage: http://github.com/metova/up_and_at_them
|
59
77
|
licenses:
|
@@ -75,9 +93,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
93
|
version: '0'
|
76
94
|
requirements: []
|
77
95
|
rubyforge_project:
|
78
|
-
rubygems_version: 2.2.
|
96
|
+
rubygems_version: 2.2.2
|
79
97
|
signing_key:
|
80
98
|
specification_version: 4
|
81
99
|
summary: A library for simplifying atomic transactions.
|
82
100
|
test_files:
|
83
|
-
-
|
101
|
+
- spec/spec_helper.rb
|
102
|
+
- spec/transaction_spec.rb
|
data/test/test_transaction.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
require 'up_and_at_them'
|
3
|
-
|
4
|
-
class TransactionTest < MiniTest::Test
|
5
|
-
def test_rollback_past_commits
|
6
|
-
flags = {1 => :pending, 2 => :pending, 3 => :pending, 4 => :pending}
|
7
|
-
|
8
|
-
commits = Array.new
|
9
|
-
(1...4).each do |i|
|
10
|
-
commits << UpAndAtThem::Commit.new { flags[i] = :committed; if i==3 ; raise 'uh oh!'; end }.on_rollback { flags[i] = :rolled_back }
|
11
|
-
end
|
12
|
-
|
13
|
-
assert_raises RuntimeError do
|
14
|
-
UpAndAtThem::Transaction.new commits
|
15
|
-
end
|
16
|
-
assert_equal :pending, flags[4]
|
17
|
-
assert_equal :committed, flags[3]
|
18
|
-
assert_equal :rolled_back, flags[2]
|
19
|
-
assert_equal :rolled_back, flags[1]
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_rollback_in_reverse_commit_order
|
23
|
-
flags = {1 => -1, 2 => -1, 3 => -1, 4 => -1}
|
24
|
-
|
25
|
-
commits = Array.new
|
26
|
-
(1...4).each do |i|
|
27
|
-
commits << UpAndAtThem::Commit.new { flags[i] = -1; if i==3 ; raise 'uh oh!'; end }.on_rollback { flags[i] = Time.now; sleep 1 }
|
28
|
-
end
|
29
|
-
|
30
|
-
assert_raises RuntimeError do
|
31
|
-
UpAndAtThem::Transaction.new commits
|
32
|
-
end
|
33
|
-
assert_equal -1, flags[4]
|
34
|
-
assert flags[3].to_f < flags[2].to_f
|
35
|
-
assert flags[2].to_f < flags[1].to_f
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_allow_no_rollback_blocks
|
39
|
-
flags = {1 => :pending, 2 => :pending, 3 => :pending, 4 => :pending}
|
40
|
-
|
41
|
-
commits = Array.new
|
42
|
-
(1...4).each do |i|
|
43
|
-
commits << UpAndAtThem::Commit.new { flags[i] = :committed; if i==3 ; raise 'fail!'; end }
|
44
|
-
end
|
45
|
-
|
46
|
-
assert_raises RuntimeError do
|
47
|
-
UpAndAtThem::Transaction.new commits
|
48
|
-
end
|
49
|
-
assert_equal :pending, flags[4]
|
50
|
-
assert_equal :committed, flags[3]
|
51
|
-
assert_equal :committed, flags[2]
|
52
|
-
assert_equal :committed, flags[1]
|
53
|
-
end
|
54
|
-
end
|