refilling_queue 0.0.4 → 0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: eb46dfea534dbaac56b171c985c0182bb9b766a7
4
+ data.tar.gz: 432cec3c6c0d9eb76218be864a86a012b4bab0d1
5
+ SHA512:
6
+ metadata.gz: 2e309d6f2d14c1234b0e8bfdbc6bcdd8d67a6e8a42451d63d3f155ee5004a7d1864a00d41ac753149c908098c5caec729e194afc0b7bc03e62f937f7608c6703
7
+ data.tar.gz: 7050b24da1fd1e3b06098d63c747c20f6218f930fb3f0aff111bd9fd15b8b6e410c2bd76c3db56b54ad563ee6e89d18a3dd33ff477db570fa3fb212d49a33868
@@ -1,3 +1,3 @@
1
1
  class RefillingQueue
2
- VERSION = '0.0.4'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -6,11 +6,13 @@ class RefillingQueue
6
6
 
7
7
  DEFAULT_OPTIONS = {
8
8
  :lock_timeout => 60,
9
- :refresh_every => nil
9
+ :refresh_every => nil,
10
+ :paginate => false
10
11
  }
11
12
 
12
13
  def initialize(client, name, options={}, &block)
13
14
  @client, @name, @block = client, name, block
15
+ @page_name = name + "/page"
14
16
  @options = DEFAULT_OPTIONS.merge(options)
15
17
  raise "Invalid keys" if (options.keys - DEFAULT_OPTIONS.keys).any?
16
18
  end
@@ -22,21 +24,48 @@ class RefillingQueue
22
24
  _pop
23
25
  end
24
26
 
27
+ def clear
28
+ lock do
29
+ mark_as_empty
30
+ _refill
31
+ end
32
+ end
33
+
25
34
  private
26
35
 
36
+ def paginate?
37
+ @options[:paginate]
38
+ end
39
+
27
40
  def _pop
28
41
  @client.lpop @name
29
42
  end
30
43
 
31
44
  def refill
32
45
  lock do
33
- results = @block.call
34
- return if results.empty?
46
+ _refill
47
+ end
48
+ end
49
+
50
+ def _refill
51
+ results = if paginate?
52
+ page = (@client.get(@page_name) || 0).to_i
53
+ @block.call(page + 1)
54
+ else
55
+ @block.call
56
+ end
57
+ if results.empty?
58
+ mark_as_empty
59
+ return
60
+ end
35
61
 
36
- @client.pipelined do
37
- @client.del @name
38
- results.each{ |r| @client.rpush @name, r } # TODO https://github.com/redis/redis-rb/issues/253
39
- @client.expire @name, @options[:refresh_every] if @options[:refresh_every]
62
+ @client.pipelined do
63
+ @client.del @name
64
+ @client.rpush @name, results
65
+ @client.expire @name, @options[:refresh_every] if @options[:refresh_every]
66
+ if paginate?
67
+ @client.incr @page_name
68
+ @client.expire @page_name, @options[:refresh_every] if @options[:refresh_every]
40
69
  end
41
70
  end
42
71
  end
@@ -45,6 +74,10 @@ class RefillingQueue
45
74
  @client.llen(@name) == 0
46
75
  end
47
76
 
77
+ def mark_as_empty
78
+ @client.del @page_name if paginate?
79
+ end
80
+
48
81
  def lock
49
82
  lock = "#{@name}_lock"
50
83
 
metadata CHANGED
@@ -1,67 +1,102 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: refilling_queue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
5
- prerelease:
4
+ version: 0.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Michael Grosser
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-11-20 00:00:00.000000000 Z
13
- dependencies: []
11
+ date: 2014-11-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bump
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
+ - !ruby/object:Gem::Dependency
42
+ name: rake
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'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2'
14
69
  description:
15
70
  email: michael@grosser.it
16
71
  executables: []
17
72
  extensions: []
18
73
  extra_rdoc_files: []
19
74
  files:
20
- - .travis.yml
21
- - Appraisals
22
- - Gemfile
23
- - Gemfile.lock
24
- - Rakefile
25
- - Readme.md
26
- - gemfiles/redis2.gemfile
27
- - gemfiles/redis2.gemfile.lock
28
- - gemfiles/redis3.gemfile
29
- - gemfiles/redis3.gemfile.lock
30
75
  - lib/refilling_queue.rb
31
76
  - lib/refilling_queue/version.rb
32
- - refilling_queue.gemspec
33
- - spec/refilling_queue_spec.rb
34
- - spec/spec_helper.rb
35
77
  homepage: http://github.com/grosser/refilling_queue
36
78
  licenses:
37
79
  - MIT
80
+ metadata: {}
38
81
  post_install_message:
39
82
  rdoc_options: []
40
83
  require_paths:
41
84
  - lib
42
85
  required_ruby_version: !ruby/object:Gem::Requirement
43
- none: false
44
86
  requirements:
45
- - - ! '>='
87
+ - - ">="
46
88
  - !ruby/object:Gem::Version
47
89
  version: '0'
48
- segments:
49
- - 0
50
- hash: 949949052394646117
51
90
  required_rubygems_version: !ruby/object:Gem::Requirement
52
- none: false
53
91
  requirements:
54
- - - ! '>='
92
+ - - ">="
55
93
  - !ruby/object:Gem::Version
56
94
  version: '0'
57
- segments:
58
- - 0
59
- hash: 949949052394646117
60
95
  requirements: []
61
96
  rubyforge_project:
62
- rubygems_version: 1.8.24
97
+ rubygems_version: 2.2.2
63
98
  signing_key:
64
- specification_version: 3
99
+ specification_version: 4
65
100
  summary: A queue that refreshes itself when it gets empty or stale, so you can keep
66
101
  popping
67
102
  test_files: []
data/.travis.yml DELETED
@@ -1,4 +0,0 @@
1
- rvm:
2
- - ree
3
- - 1.9.2
4
- - 1.9.3
data/Appraisals DELETED
@@ -1,5 +0,0 @@
1
- ["2", "3"].each do |version|
2
- appraise "redis#{version}" do
3
- gem "redis", "~>#{version}.0"
4
- end
5
- end
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- source :rubygems
2
- gemspec
3
-
4
- gem 'appraisal'
5
- gem 'bump'
6
- gem 'rake'
7
- gem 'rspec', '~>2'
8
- gem 'redis'
data/Gemfile.lock DELETED
@@ -1,34 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- refilling_queue (0.0.4)
5
-
6
- GEM
7
- remote: http://rubygems.org/
8
- specs:
9
- appraisal (0.5.1)
10
- bundler
11
- rake
12
- bump (0.3.5)
13
- diff-lcs (1.1.3)
14
- rake (0.9.2)
15
- redis (3.0.1)
16
- rspec (2.6.0)
17
- rspec-core (~> 2.6.0)
18
- rspec-expectations (~> 2.6.0)
19
- rspec-mocks (~> 2.6.0)
20
- rspec-core (2.6.4)
21
- rspec-expectations (2.6.0)
22
- diff-lcs (~> 1.1.2)
23
- rspec-mocks (2.6.0)
24
-
25
- PLATFORMS
26
- ruby
27
-
28
- DEPENDENCIES
29
- appraisal
30
- bump
31
- rake
32
- redis
33
- refilling_queue!
34
- rspec (~> 2)
data/Rakefile DELETED
@@ -1,11 +0,0 @@
1
- require 'bundler/gem_tasks'
2
- require 'appraisal'
3
- require 'bump/tasks'
4
-
5
- task :spec do
6
- sh "rspec spec/"
7
- end
8
-
9
- task :default do
10
- sh "bundle exec rake appraisal:install && bundle exec rake appraisal spec"
11
- end
data/Readme.md DELETED
@@ -1,34 +0,0 @@
1
- A queue that refreshes itself when it gets empty or stale, so you can keep popping
2
-
3
- Install
4
- =======
5
-
6
- gem install refilling_queue
7
-
8
- Usage
9
- =====
10
-
11
- queue = RefillingQueue.new resque_client, "my_queue", :refresh_every => 30.seconds do
12
- expensive_operation.map(&:id)
13
- end
14
-
15
- begin
16
- queue.pop
17
- rescue RefillingQueue::Locked
18
- # queue was empty, refilling failed because other process is already trying it
19
- end
20
-
21
- queue.pop -> return id
22
- ... # queue empty ?
23
- queue.pop -> run block -> store new ids -> return id
24
- ... # 30 seconds elapsed (global expires_at stored in reque_client) ?
25
- queue.pop -> run block -> store new ids -> return id
26
- ...
27
- queue.pop -> run block -> empty result -> return nil
28
-
29
- Author
30
- ======
31
- [Michael Grosser](http://grosser.it)<br/>
32
- michael@grosser.it<br/>
33
- License: MIT<br/>
34
- [![Build Status](https://secure.travis-ci.org/grosser/refilling_queue.png)](http://travis-ci.org/grosser/refilling_queue)
@@ -1,11 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source :rubygems
4
-
5
- gem "appraisal"
6
- gem "bump"
7
- gem "rake"
8
- gem "rspec", "~>2"
9
- gem "redis", "~>2.0"
10
-
11
- gemspec :path=>"../"
@@ -1,34 +0,0 @@
1
- PATH
2
- remote: /Users/mgrosser/code/tools/refilling_queue
3
- specs:
4
- refilling_queue (0.0.3)
5
-
6
- GEM
7
- remote: http://rubygems.org/
8
- specs:
9
- appraisal (0.5.1)
10
- bundler
11
- rake
12
- bump (0.3.5)
13
- diff-lcs (1.1.3)
14
- rake (10.0.2)
15
- redis (2.2.2)
16
- rspec (2.11.0)
17
- rspec-core (~> 2.11.0)
18
- rspec-expectations (~> 2.11.0)
19
- rspec-mocks (~> 2.11.0)
20
- rspec-core (2.11.1)
21
- rspec-expectations (2.11.3)
22
- diff-lcs (~> 1.1.3)
23
- rspec-mocks (2.11.3)
24
-
25
- PLATFORMS
26
- ruby
27
-
28
- DEPENDENCIES
29
- appraisal
30
- bump
31
- rake
32
- redis (~> 2.0)
33
- refilling_queue!
34
- rspec (~> 2)
@@ -1,11 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source :rubygems
4
-
5
- gem "appraisal"
6
- gem "bump"
7
- gem "rake"
8
- gem "rspec", "~>2"
9
- gem "redis", "~>3.0"
10
-
11
- gemspec :path=>"../"
@@ -1,34 +0,0 @@
1
- PATH
2
- remote: /Users/mgrosser/code/tools/refilling_queue
3
- specs:
4
- refilling_queue (0.0.3)
5
-
6
- GEM
7
- remote: http://rubygems.org/
8
- specs:
9
- appraisal (0.5.1)
10
- bundler
11
- rake
12
- bump (0.3.5)
13
- diff-lcs (1.1.3)
14
- rake (10.0.2)
15
- redis (3.0.2)
16
- rspec (2.11.0)
17
- rspec-core (~> 2.11.0)
18
- rspec-expectations (~> 2.11.0)
19
- rspec-mocks (~> 2.11.0)
20
- rspec-core (2.11.1)
21
- rspec-expectations (2.11.3)
22
- diff-lcs (~> 1.1.3)
23
- rspec-mocks (2.11.3)
24
-
25
- PLATFORMS
26
- ruby
27
-
28
- DEPENDENCIES
29
- appraisal
30
- bump
31
- rake
32
- redis (~> 3.0)
33
- refilling_queue!
34
- rspec (~> 2)
@@ -1,12 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
- name = "refilling_queue"
3
- require "#{name}/version"
4
-
5
- Gem::Specification.new name, RefillingQueue::VERSION do |s|
6
- s.summary = "A queue that refreshes itself when it gets empty or stale, so you can keep popping"
7
- s.authors = ["Michael Grosser"]
8
- s.email = "michael@grosser.it"
9
- s.homepage = "http://github.com/grosser/#{name}"
10
- s.files = `git ls-files`.split("\n")
11
- s.license = 'MIT'
12
- end
@@ -1,112 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe RefillingQueue do
4
- def kill_all_threads
5
- Thread.list.each {|thread| thread.exit unless thread == Thread.current }
6
- end
7
-
8
- let(:client){ Redis.new }
9
-
10
- before do
11
- kill_all_threads
12
- client.flushdb
13
- end
14
-
15
- after :all do
16
- `rm -f dump.rdb`
17
- end
18
-
19
- it "has a VERSION" do
20
- RefillingQueue::VERSION.should =~ /^[\.\da-z]+$/
21
- end
22
-
23
- context "#initialize" do
24
- it "does not fill itself when started full" do
25
- x = 0
26
- RefillingQueue.new(client, "x"){ x = 1 }
27
- x.should == 0
28
- end
29
- end
30
-
31
- context "#pop" do
32
- it "removes an element" do
33
- queue = RefillingQueue.new(client, "x"){ [1,2,3,4] }
34
- queue.pop.should == "1"
35
- queue.pop.should == "2"
36
- queue.pop.should == "3"
37
- end
38
-
39
- it "only tries to refill once" do
40
- calls = []
41
- RefillingQueue.new(client, "x"){ calls << 1; [] }.pop.should == nil
42
- calls.should == [1]
43
- end
44
-
45
- it "refills itself if queue gets empty" do
46
- content = [1]
47
- queue = RefillingQueue.new(client, "x"){ content }
48
- queue.pop.should == "1"
49
- content.replace [4,5]
50
- queue.pop.should == "4"
51
- queue.pop.should == "5"
52
- queue.pop.should == "4"
53
- end
54
-
55
- it "refills itself when it expires" do
56
- content = [1,2,3]
57
- queue = RefillingQueue.new(client, "x", :refresh_every => 1){ content }
58
-
59
- queue.pop.should == "1"
60
- content.replace [4,5]
61
- queue.pop.should == "2"
62
- sleep 2
63
-
64
- queue.pop.should == "4"
65
- end
66
- end
67
-
68
- context "with multiple actors" do
69
- it "only refills once" do
70
- called = []
71
-
72
- # lock-blocker
73
- Thread.new do
74
- RefillingQueue.new(client, "x"){ called << 1; sleep 0.3; called << 2; [] }.pop
75
- end
76
- sleep 0.1
77
-
78
- # blocked
79
- locked = false
80
- queue = RefillingQueue.new(client, "x"){ called << 3; [] }
81
- begin
82
- queue.pop
83
- fail
84
- rescue RefillingQueue::Locked
85
- locked = true
86
- end
87
- sleep 0.3
88
-
89
- called.should == [1, 2]
90
- locked.should == true
91
- end
92
-
93
- it "can refill after refill is complete" do
94
- called = []
95
- RefillingQueue.new(client, "x"){ called << 1; [1] }.pop
96
- RefillingQueue.new(client, "x"){ called << 2; [1] }.pop
97
- called.should == [1,2]
98
- end
99
-
100
- it "can refill if lock expired" do
101
- called = []
102
- RefillingQueue.new(client, "x", :lock_timeout => 1){ called << 1; [1] }.pop
103
- Thread.new do
104
- # lock-blocker
105
- RefillingQueue.new(client, "x", :lock_timeout => 1){ sleep 3; called << 2; [1] }.pop
106
- end
107
- sleep 2
108
- RefillingQueue.new(client, "x", :lock_timeout => 1){ called << 3; [1] }.pop
109
- called.should == [1,3]
110
- end
111
- end
112
- end
data/spec/spec_helper.rb DELETED
@@ -1,3 +0,0 @@
1
- $LOAD_PATH.unshift 'lib'
2
- require 'refilling_queue'
3
- require 'redis'