retryable_record 0.0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  coverage
2
+ Gemfile.lock
2
3
  pkg
3
4
  doc
4
5
  .yardoc
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm @retryable_record --create
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - ree
4
+ - 1.9.3
5
+ - jruby-18mode
6
+ - jruby-19mode
7
+ - rbx-18mode
8
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in retryable_record.gemspec
4
+ gemspec
@@ -2,9 +2,11 @@
2
2
 
3
3
  Retries an operation on an ActiveRecord until no StaleObjectError is being raised.
4
4
 
5
- Source[http://github.com/splattael/retryable_record] |
6
- RDoc[http://rdoc.info/projects/splattael/retryable_record] |
7
- Metrics[http://getcaliper.com/caliper/project?repo=http%3A%2F%2Fgemcutter.org%2Fgems%2Fretryable_record]
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
- require 'rubygems'
2
- require 'rake'
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
3
 
4
- begin
5
- require 'jeweler'
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
- begin
33
- require 'rcov/rcovtask'
34
- Rcov::RcovTask.new do |test|
35
- test.libs << 'test'
36
- test.pattern = 'test/**/*_test.rb'
37
- test.verbose = true
38
- end
39
- rescue LoadError
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
@@ -0,0 +1,3 @@
1
+ module RetryableRecord
2
+ VERSION = "0.1.1"
3
+ end
@@ -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 |s|
7
- s.name = %q{retryable_record}
8
- s.version = "0.0.1"
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
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Peter Suschlik"]
12
- s.date = %q{2010-02-11}
13
- s.email = %q{peter@suschlik.de}
14
- s.extra_rdoc_files = [
15
- "LICENSE",
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
- if s.respond_to? :specification_version then
42
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
- s.specification_version = 3
18
+ gem.add_runtime_dependency 'activerecord', '>= 3'
44
19
 
45
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
46
- s.add_development_dependency(%q<riot>, [">= 0.10.11"])
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
-
@@ -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 'teststrap'
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
- FakeRecord.new
8
+ record.retryable do
9
+ record.concurrent_modification!
10
+ record.save!
11
+ end
6
12
  end
7
13
 
8
- asserts("that block return value") do
9
- topic.retryable { :return_value }
10
- end.equals(:return_value)
14
+ context :retryable do
15
+ context "without retry" do
16
+ let(:retries) { 0 }
11
17
 
12
- asserts("that other errors") do
13
- topic.retryable do
14
- raise "other error"
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
- context "saves without retries" do
19
- hookup do
20
- topic.retryable do
21
- topic.save
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
- asserts("save counter") { topic.counter[:save] }.equals(1)
26
- asserts("reload counter") { topic.counter[:reload] }.equals(0)
27
- end
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
- asserts("save counter") { topic.counter[:save] }.equals(1)
45
- asserts("reload counter") { topic.counter[:reload] }.equals(1)
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.0.1
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
- date: 2010-02-11 00:00:00 +01:00
13
- default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: riot
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
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: 0.10.11
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: riot_notifier
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
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
35
- - !ruby/object:Gem::Dependency
36
- name: yard
37
- type: :development
38
- version_requirement:
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
- extra_rdoc_files:
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
- - test/teststrap.rb
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
- - --charset=UTF-8
73
- require_paths:
88
+ rdoc_options: []
89
+ require_paths:
74
90
  - lib
75
- required_ruby_version: !ruby/object:Gem::Requirement
76
- requirements:
77
- - - ">="
78
- - !ruby/object:Gem::Version
79
- version: "0"
80
- version:
81
- required_rubygems_version: !ruby/object:Gem::Requirement
82
- requirements:
83
- - - ">="
84
- - !ruby/object:Gem::Version
85
- version: "0"
86
- version:
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.3.5
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 raised.
94
- test_files:
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
@@ -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