retryable_record 0.0.1 → 0.1.1
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 +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/README.rdoc +12 -7
- data/Rakefile +13 -46
- data/lib/retryable_record/version.rb +3 -0
- data/retryable_record.gemspec +16 -54
- data/test/helper.rb +46 -0
- data/test/retryable_record_test.rb +29 -32
- metadata +84 -68
- data/test/teststrap.rb +0 -31
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm @retryable_record --create
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.rdoc
CHANGED
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
Retries an operation on an ActiveRecord until no StaleObjectError is being raised.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
Gem[https://rubygems.org/gems/retryable_record] |
|
6
|
+
Source[http://github.com/neopoly/retryable_record] |
|
7
|
+
RDoc[http://rdoc.info/projects/neopoly/retryable_record] |
|
8
|
+
{<img src="https://secure.travis-ci.org/neopoly/retryable_record.png?branch=master" alt="Build Status" />}[http://travis-ci.org/neopoly/retryable_record]
|
9
|
+
|
8
10
|
|
9
11
|
== Usage
|
10
12
|
|
@@ -21,6 +23,13 @@ Metrics[http://getcaliper.com/caliper/project?repo=http%3A%2F%2Fgemcutter.org%2F
|
|
21
23
|
user.save!
|
22
24
|
end
|
23
25
|
|
26
|
+
== Credits
|
27
|
+
|
28
|
+
Inspired by
|
29
|
+
* http://vision-media.ca/resources/ruby/better-ruby-retryable-method
|
30
|
+
* http://blog.codefront.net/2008/01/14/retrying-code-blocks-in-ruby-on-exceptions-whatever/
|
31
|
+
* http://github.com/carlo/retryable
|
32
|
+
|
24
33
|
== TODO
|
25
34
|
|
26
35
|
* Better example in README
|
@@ -35,7 +44,3 @@ Metrics[http://getcaliper.com/caliper/project?repo=http%3A%2F%2Fgemcutter.org%2F
|
|
35
44
|
* Commit, do not mess with rakefile, version, or history.
|
36
45
|
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
37
46
|
* Send me a pull request. Bonus points for topic branches.
|
38
|
-
|
39
|
-
== Copyright
|
40
|
-
|
41
|
-
Copyright (c) 2010 Peter Suschlik. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -1,27 +1,10 @@
|
|
1
|
-
|
2
|
-
require
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "retryable_record"
|
8
|
-
gem.summary = %Q{Retries an operation on an ActiveRecord until no StaleObjectError is being raised.}
|
9
|
-
# TODO gem.description = %Q{}
|
10
|
-
gem.email = "peter@suschlik.de"
|
11
|
-
gem.homepage = "http://github.com/splattael/retryable_record"
|
12
|
-
gem.authors = ["Peter Suschlik"]
|
13
|
-
|
14
|
-
gem.add_development_dependency "riot", ">= 0.10.11"
|
15
|
-
gem.add_development_dependency "riot_notifier"
|
16
|
-
gem.add_development_dependency "yard"
|
17
|
-
|
18
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
|
-
end
|
20
|
-
Jeweler::GemcutterTasks.new
|
21
|
-
rescue LoadError
|
22
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
23
|
-
end
|
4
|
+
desc 'Default: run unit tests.'
|
5
|
+
task :default => :test
|
24
6
|
|
7
|
+
# Test
|
25
8
|
require 'rake/testtask'
|
26
9
|
Rake::TestTask.new(:test) do |test|
|
27
10
|
test.libs << 'lib' << 'test'
|
@@ -29,28 +12,12 @@ Rake::TestTask.new(:test) do |test|
|
|
29
12
|
test.verbose = true
|
30
13
|
end
|
31
14
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
task :rcov do
|
41
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
task :test => :check_dependencies
|
46
|
-
|
47
|
-
task :default => :test
|
48
|
-
|
49
|
-
begin
|
50
|
-
require 'yard'
|
51
|
-
YARD::Rake::YardocTask.new
|
52
|
-
rescue LoadError
|
53
|
-
task :yardoc do
|
54
|
-
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
55
|
-
end
|
15
|
+
# RDoc
|
16
|
+
require 'rdoc/task'
|
17
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'doc'
|
19
|
+
rdoc.title = 'retryable_record'
|
20
|
+
rdoc.options << '--line-numbers'
|
21
|
+
rdoc.rdoc_files.include('README.rdoc')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
23
|
end
|
data/retryable_record.gemspec
CHANGED
@@ -1,60 +1,22 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/retryable_record/version', __FILE__)
|
5
3
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Peter Suschlik"]
|
6
|
+
gem.email = ["ps@neopoly.de"]
|
7
|
+
gem.description = %q{Retries an operation on an ActiveRecord until no StaleObjectError is being raised.}
|
8
|
+
gem.summary = %q{Retries an operation on an ActiveRecord until no StaleObjectError is being raised.}
|
9
|
+
gem.homepage = "https://github.com/neopoly/retryable_record"
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
"README.rdoc"
|
17
|
-
]
|
18
|
-
s.files = [
|
19
|
-
".document",
|
20
|
-
".gitignore",
|
21
|
-
"LICENSE",
|
22
|
-
"README.rdoc",
|
23
|
-
"Rakefile",
|
24
|
-
"VERSION",
|
25
|
-
"lib/retryable_record.rb",
|
26
|
-
"retryable_record.gemspec",
|
27
|
-
"test.watchr",
|
28
|
-
"test/retryable_record_test.rb",
|
29
|
-
"test/teststrap.rb"
|
30
|
-
]
|
31
|
-
s.homepage = %q{http://github.com/splattael/retryable_record}
|
32
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
33
|
-
s.require_paths = ["lib"]
|
34
|
-
s.rubygems_version = %q{1.3.5}
|
35
|
-
s.summary = %q{Retries an operation on an ActiveRecord until no StaleObjectError is being raised.}
|
36
|
-
s.test_files = [
|
37
|
-
"test/retryable_record_test.rb",
|
38
|
-
"test/teststrap.rb"
|
39
|
-
]
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "retryable_record"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = RetryableRecord::VERSION
|
40
17
|
|
41
|
-
|
42
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
43
|
-
s.specification_version = 3
|
18
|
+
gem.add_runtime_dependency 'activerecord', '>= 3'
|
44
19
|
|
45
|
-
|
46
|
-
|
47
|
-
s.add_development_dependency(%q<riot_notifier>, [">= 0"])
|
48
|
-
s.add_development_dependency(%q<yard>, [">= 0"])
|
49
|
-
else
|
50
|
-
s.add_dependency(%q<riot>, [">= 0.10.11"])
|
51
|
-
s.add_dependency(%q<riot_notifier>, [">= 0"])
|
52
|
-
s.add_dependency(%q<yard>, [">= 0"])
|
53
|
-
end
|
54
|
-
else
|
55
|
-
s.add_dependency(%q<riot>, [">= 0.10.11"])
|
56
|
-
s.add_dependency(%q<riot_notifier>, [">= 0"])
|
57
|
-
s.add_dependency(%q<yard>, [">= 0"])
|
58
|
-
end
|
20
|
+
gem.add_development_dependency 'rake'
|
21
|
+
gem.add_development_dependency 'minitest', '~> 3.2.0'
|
59
22
|
end
|
60
|
-
|
data/test/helper.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require 'minitest/unit'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
|
6
|
+
require 'retryable_record'
|
7
|
+
|
8
|
+
class Spec < MiniTest::Spec
|
9
|
+
class << self
|
10
|
+
alias :context :describe
|
11
|
+
alias :test :it
|
12
|
+
alias :setup :before
|
13
|
+
alias :teardown :after
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class FakeRecord
|
18
|
+
include RetryableRecord
|
19
|
+
|
20
|
+
attr_accessor :counter
|
21
|
+
|
22
|
+
def initialize(retries_left = 0)
|
23
|
+
@counter = Hash.new(0)
|
24
|
+
@counter[:retries_left] = retries_left
|
25
|
+
end
|
26
|
+
|
27
|
+
def reload
|
28
|
+
@counter[:reload] += 1
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def save!
|
33
|
+
@counter[:save] += 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def retries_left?
|
37
|
+
@counter[:retries_left] > 0
|
38
|
+
end
|
39
|
+
|
40
|
+
def concurrent_modification!
|
41
|
+
if retries_left?
|
42
|
+
@counter[:retries_left] -= 1
|
43
|
+
raise ActiveRecord::StaleObjectError.new self, :save
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,47 +1,44 @@
|
|
1
|
-
require '
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class RetryableRecordTest < Spec
|
4
|
+
let(:retries) { 0 }
|
5
|
+
let(:record) { FakeRecord.new(retries) }
|
2
6
|
|
3
|
-
context "FakeRecord" do
|
4
7
|
setup do
|
5
|
-
|
8
|
+
record.retryable do
|
9
|
+
record.concurrent_modification!
|
10
|
+
record.save!
|
11
|
+
end
|
6
12
|
end
|
7
13
|
|
8
|
-
|
9
|
-
|
10
|
-
|
14
|
+
context :retryable do
|
15
|
+
context "without retry" do
|
16
|
+
let(:retries) { 0 }
|
11
17
|
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
test "saves and does not retry" do
|
19
|
+
assert_equal 0, record.counter[:reload]
|
20
|
+
assert_equal 1, record.counter[:save]
|
21
|
+
end
|
15
22
|
end
|
16
|
-
end.raises(RuntimeError, "other error")
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
context "with retry once" do
|
25
|
+
let(:retries) { 5 }
|
26
|
+
|
27
|
+
test "saves and reloads 5 times" do
|
28
|
+
assert_equal 5, record.counter[:reload]
|
29
|
+
assert_equal 1, record.counter[:save]
|
22
30
|
end
|
23
31
|
end
|
24
32
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
context "saves with 1 retry" do
|
30
|
-
hookup do
|
31
|
-
topic.retryable do
|
32
|
-
i = 0
|
33
|
-
topic.retryable do
|
34
|
-
if i == 0
|
35
|
-
i += 1
|
36
|
-
topic.concurrent_modification!
|
37
|
-
end
|
38
|
-
|
39
|
-
topic.save
|
33
|
+
test "does not rescue other errors" do
|
34
|
+
assert_raises RuntimeError do
|
35
|
+
record.retryable do
|
36
|
+
raise "foo"
|
40
37
|
end
|
41
38
|
end
|
42
|
-
end
|
43
39
|
|
44
|
-
|
45
|
-
|
40
|
+
assert_equal 0, record.counter[:reload]
|
41
|
+
assert_equal 1, record.counter[:save]
|
42
|
+
end
|
46
43
|
end
|
47
44
|
end
|
metadata
CHANGED
@@ -1,96 +1,112 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: retryable_record
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
+
authors:
|
7
8
|
- Peter Suschlik
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
date: 2012-07-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
17
38
|
type: :development
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: minitest
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 3.2.0
|
27
54
|
type: :development
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
40
|
-
requirements:
|
41
|
-
- - ">="
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: "0"
|
44
|
-
version:
|
45
|
-
description:
|
46
|
-
email: peter@suschlik.de
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.2.0
|
62
|
+
description: Retries an operation on an ActiveRecord until no StaleObjectError is
|
63
|
+
being raised.
|
64
|
+
email:
|
65
|
+
- ps@neopoly.de
|
47
66
|
executables: []
|
48
|
-
|
49
67
|
extensions: []
|
50
|
-
|
51
|
-
|
52
|
-
- LICENSE
|
53
|
-
- README.rdoc
|
54
|
-
files:
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
55
70
|
- .document
|
56
71
|
- .gitignore
|
72
|
+
- .rvmrc
|
73
|
+
- .travis.yml
|
74
|
+
- Gemfile
|
57
75
|
- LICENSE
|
58
76
|
- README.rdoc
|
59
77
|
- Rakefile
|
60
78
|
- VERSION
|
61
79
|
- lib/retryable_record.rb
|
80
|
+
- lib/retryable_record/version.rb
|
62
81
|
- retryable_record.gemspec
|
63
82
|
- test.watchr
|
83
|
+
- test/helper.rb
|
64
84
|
- test/retryable_record_test.rb
|
65
|
-
|
66
|
-
has_rdoc: true
|
67
|
-
homepage: http://github.com/splattael/retryable_record
|
85
|
+
homepage: https://github.com/neopoly/retryable_record
|
68
86
|
licenses: []
|
69
|
-
|
70
87
|
post_install_message:
|
71
|
-
rdoc_options:
|
72
|
-
|
73
|
-
require_paths:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
74
90
|
- lib
|
75
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
87
103
|
requirements: []
|
88
|
-
|
89
104
|
rubyforge_project:
|
90
|
-
rubygems_version: 1.
|
105
|
+
rubygems_version: 1.8.24
|
91
106
|
signing_key:
|
92
107
|
specification_version: 3
|
93
|
-
summary: Retries an operation on an ActiveRecord until no StaleObjectError is being
|
94
|
-
|
108
|
+
summary: Retries an operation on an ActiveRecord until no StaleObjectError is being
|
109
|
+
raised.
|
110
|
+
test_files:
|
111
|
+
- test/helper.rb
|
95
112
|
- test/retryable_record_test.rb
|
96
|
-
- test/teststrap.rb
|
data/test/teststrap.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'riot'
|
3
|
-
require 'riot_notifier'
|
4
|
-
|
5
|
-
require 'retryable_record'
|
6
|
-
|
7
|
-
Riot.reporter = RiotNotifier
|
8
|
-
|
9
|
-
class FakeRecord
|
10
|
-
include RetryableRecord
|
11
|
-
|
12
|
-
attr_accessor :counter
|
13
|
-
|
14
|
-
def initialize
|
15
|
-
@counter = Hash.new(0)
|
16
|
-
end
|
17
|
-
|
18
|
-
def reload
|
19
|
-
@counter[:reload] += 1
|
20
|
-
self
|
21
|
-
end
|
22
|
-
|
23
|
-
def save
|
24
|
-
@counter[:save] += 1
|
25
|
-
true
|
26
|
-
end
|
27
|
-
|
28
|
-
def concurrent_modification!
|
29
|
-
raise ActiveRecord::StaleObjectError
|
30
|
-
end
|
31
|
-
end
|