ar-resque-counter-cache 3.0.2 → 3.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/README.md CHANGED
@@ -18,11 +18,15 @@ How does ar-resque-counter-cache address these issues? It uses Redis as a
18
18
  temporary counter cache and Resque to actually update the counter cache column
19
19
  sometime in the future. For example, let's say a single Post gets 1000 comments
20
20
  very quickly. This will set a key in Redis indicating that there is a delta of
21
- +1000 for that Post's comments_count column. It will also queue 1000 Resque
22
- jobs. This is where resque-lock-timeout comes in. Only one of those jobs will
23
- be allowed to run at a time. Once a job acquires the lock it removes all other
24
- instances of that job from the queue (see
25
- IncrementCountersWorker.around\_perform\_lock1).
21
+ +1000 for that Post's comments_count column. Previously (in versions 3.0.2 and
22
+ below), it would also queue 1000 Resque jobs. This is where resque-lock-timeout
23
+ came in. Only one of those jobs will be allowed to run at a time. Once a job
24
+ acquires the lock it removes all other instances of that job from the queue
25
+ (see IncrementCountersWorker.around\_perform\_lock1) using Redis's lrem
26
+ command. Unfortunately we ran into some giant Redis cpu overload with lrems
27
+ during traffic spikes and decided to switch to the simpler resque-loner gem.
28
+ This gem instead uses a key to determine whether or not to enqueue a given job
29
+ in the first place.
26
30
 
27
31
  You use it like such:
28
32
 
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
9
9
  s.authors = ["Aaron Gibralter"]
10
10
  s.email = ["aaron.gibralter@gmail.com"]
11
11
  s.homepage = "http://github.com/agibralter/ar-resque-counter-cache"
12
- s.summary = %q{Increment ActiveRecord's counter cache column asynchronously using Resque (and resque-lock-timeout).}
13
- s.description = %q{Increment ActiveRecord's counter cache column asynchronously using Resque (and resque-lock-timeout).}
12
+ s.summary = %q{Increment ActiveRecord's counter cache column asynchronously using Resque (and resque-loner).}
13
+ s.description = %q{Increment ActiveRecord's counter cache column asynchronously using Resque (and resque-loner).}
14
14
 
15
15
  s.rubyforge_project = "ar-resque-counter-cache"
16
16
 
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_dependency "activerecord", "~> 3.2"
23
23
  s.add_dependency "resque", "~> 1.0"
24
- s.add_dependency "resque-lock-timeout", "~> 0.4"
24
+ s.add_dependency "resque-loner", "~> 1.2"
25
25
 
26
26
  s.add_development_dependency "rspec", "~> 2.4.0"
27
27
  s.add_development_dependency "sqlite3-ruby", "~> 1.3.3"
@@ -1,5 +1,5 @@
1
1
  require 'resque'
2
- require 'resque-lock-timeout'
2
+ require 'resque-loner'
3
3
 
4
4
  module ArResqueCounterCache
5
5
 
@@ -10,13 +10,6 @@ module ArResqueCounterCache
10
10
  end
11
11
  end
12
12
 
13
- # The default lock_timeout is 60 seconds.
14
- def self.resque_lock_timeout=(lock_timeout)
15
- IncrementCountersWorker.class_eval do
16
- @lock_timeout = lock_timeout
17
- end
18
- end
19
-
20
13
  # If you don't want to use Resque's Redis connection to store the temporary
21
14
  # counter caches, you can set a different connection here.
22
15
  def self.redis=(redis)
@@ -26,14 +19,13 @@ module ArResqueCounterCache
26
19
  end
27
20
 
28
21
  # ArResqueCounterCache will very quickly increment a counter cache in Redis,
29
- # which will then later be updated by a Resque job. Using
30
- # require-lock-timeout, we can ensure that only one job per ___ is running
31
- # at a time.
22
+ # which will then later be updated by a Resque job. Using require-loner, we
23
+ # can ensure that only one job per payload is enqueued at a time.
32
24
  class IncrementCountersWorker
33
25
 
34
- extend ::Resque::Plugins::LockTimeout
26
+ include Resque::Plugins::UniqueJob
35
27
  @queue = :counter_caches
36
- @lock_timeout = 60
28
+ @loner_ttl = 3600 # Don't hold lock for more than 1 hour...
37
29
 
38
30
  def self.cache_and_enqueue(parent_class, id, column, direction)
39
31
  parent_class = parent_class.to_s
@@ -57,35 +49,11 @@ module ArResqueCounterCache
57
49
  args.join('-')
58
50
  end
59
51
 
60
- # Try again later if lock is in use.
61
- def self.lock_failed(*args)
62
- ::Resque.enqueue(self, *args)
63
- end
64
-
65
52
  # args: (parent_class, id, column)
66
53
  def self.cache_key(*args)
67
54
  "ar-resque-counter-cache:#{identifier(*args)}"
68
55
  end
69
56
 
70
- # The name of this method ensures that it runs within around_perform_lock.
71
- #
72
- # We've leveraged resque-lock-timeout to ensure that only one job is
73
- # running at a time. Now, this around filter essentially ensures that only
74
- # one job per parent-column can sit on the queue at once. Since the
75
- # cache_key entry in redis stores the most up-to-date delta for the
76
- # parent's counter cache, we don't have to actually perform the
77
- # Klass.update_counters for every increment/decrement. We can batch
78
- # process!
79
- def self.around_perform_lock1(*args)
80
- # Remove all other instances of this job (with the same args) from the
81
- # queue. Uses LREM (http://code.google.com/p/redis/wiki/LremCommand) which
82
- # takes the form: "LREM key count value" and if count == 0 removes all
83
- # instances of value from the list.
84
- redis_job_value = ::Resque.encode(:class => self.to_s, :args => args)
85
- ::Resque.redis.lrem("queue:#{@queue}", 0, redis_job_value)
86
- yield
87
- end
88
-
89
57
  def self.perform(parent_class, id, column)
90
58
  key = cache_key(parent_class, id, column)
91
59
  if (delta = redis.getset(key, 0).to_i) != 0
@@ -1,3 +1,3 @@
1
1
  module ArResqueCounterCache
2
- VERSION = '3.0.2'
2
+ VERSION = '3.1.0'
3
3
  end
@@ -24,9 +24,9 @@ describe "integration" do
24
24
  @post2.count_of_comments.should == 0
25
25
 
26
26
  # 2 for posts incrementing users' posts counts
27
- # 3 for comments incrementing users' comments counts
28
- # 3 for comments incrementing posts' comments counts
29
- Resque.size(:testing).should == 8
27
+ # 1 for comments incrementing users' comments counts
28
+ # 2 for comments incrementing posts' comments counts
29
+ Resque.size(:testing).should == 5
30
30
 
31
31
  # [ArResqueCounterCache::IncrementCountersWorker, "User", 1, "posts_count"]
32
32
  perform_next_job
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar-resque-counter-cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.2
4
+ version: 3.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-27 00:00:00.000000000 Z
12
+ date: 2013-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -44,13 +44,13 @@ dependencies:
44
44
  - !ruby/object:Gem::Version
45
45
  version: '1.0'
46
46
  - !ruby/object:Gem::Dependency
47
- name: resque-lock-timeout
47
+ name: resque-loner
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: '0.4'
53
+ version: '1.2'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0.4'
61
+ version: '1.2'
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: rspec
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -92,7 +92,7 @@ dependencies:
92
92
  - !ruby/object:Gem::Version
93
93
  version: 1.3.3
94
94
  description: Increment ActiveRecord's counter cache column asynchronously using Resque
95
- (and resque-lock-timeout).
95
+ (and resque-loner).
96
96
  email:
97
97
  - aaron.gibralter@gmail.com
98
98
  executables: []
@@ -138,7 +138,7 @@ rubygems_version: 1.8.24
138
138
  signing_key:
139
139
  specification_version: 3
140
140
  summary: Increment ActiveRecord's counter cache column asynchronously using Resque
141
- (and resque-lock-timeout).
141
+ (and resque-loner).
142
142
  test_files:
143
143
  - spec/ar_resque_counter_cache/active_record_spec.rb
144
144
  - spec/integration_spec.rb