turnpike 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use 1.9.2@turnpike
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # CHANGELOG
2
+
3
+ See [here](http://code.papercavalier.com/turnpike).
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in turnpike.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # Turnpike
2
+
3
+ Turnpike is a Redis-backed processing queue.
4
+
5
+ # Usage
6
+
7
+ Set up:
8
+
9
+ ```ruby
10
+ require "turnpike"
11
+
12
+ queue = Turnpike.new(:processing_queue)
13
+ ```
14
+
15
+ Queue:
16
+
17
+ ```ruby
18
+ queue << "unit of work"
19
+ ```
20
+
21
+ Process:
22
+
23
+ ```ruby
24
+ queue.each do |work|
25
+ # create value
26
+ end
27
+
28
+ # alternatively
29
+ queue.each_slice(10) do |slice)
30
+ # create value
31
+ end
32
+ ```
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rake/testtask'
4
+
5
+ task :default => :test
6
+
7
+ Rake::TestTask.new do |test|
8
+ test.libs << 'test'
9
+ test.test_files = FileList['test/**/*_test.rb']
10
+ end
data/lib/turnpike.rb ADDED
@@ -0,0 +1,121 @@
1
+ require 'redis'
2
+
3
+ # A Redis-backed queue.
4
+ class Turnpike
5
+ REDIS_VERSION = Redis.current.info['redis_version']
6
+ TIMEOUT = ENV['TURNPIKE_TIMEOUT'] || 2
7
+ VERSION = '0.0.1'
8
+
9
+ # The name of the queue.
10
+ attr :name
11
+
12
+ # Creates a new queue.
13
+ #
14
+ # Takes an optional name.
15
+ def initialize(name = 'default')
16
+ @name = "turnpike:#{name}"
17
+ end
18
+
19
+ # Removes all queued items.
20
+ def clear
21
+ redis.del(name)
22
+ end
23
+
24
+ # Calls block once for each queued item.
25
+ #
26
+ # Takes an optional boolean argument to specify if the command should block
27
+ # the connection when the queue is empty. This argument defaults to false.
28
+ def each(blocking = false, &block)
29
+ while item = shift(blocking)
30
+ block.call(item)
31
+ end
32
+ end
33
+
34
+ # Iterates the given block for each slice of `n` queued items.
35
+ def each_slice(n, blocking = false, &block)
36
+ slice = []
37
+
38
+ each(blocking) do |item|
39
+ slice << item
40
+ if slice.size == n
41
+ yield slice
42
+ slice = []
43
+ end
44
+ end
45
+
46
+ yield slice unless slice.empty?
47
+ end
48
+
49
+ # Returns `true` if the queue is empty.
50
+ def empty?
51
+ length == 0
52
+ end
53
+
54
+ # Returns the length of the queue.
55
+ def length
56
+ redis.llen(name)
57
+ end
58
+ alias size length
59
+
60
+ # Returns an array of items currently queued.
61
+ #
62
+ # `start` is an integer and indicates the start offset, 0 being the first
63
+ # queued item. If negative, it indicates the offset from the end, -1 being
64
+ # the last queued item.
65
+ #
66
+ # `count` is also an integer and indicates the number of items to return.
67
+ def peek(start, count)
68
+ redis.lrange(name, start, count)
69
+ end
70
+
71
+ # Retrieves the last queued item.
72
+ #
73
+ # Takes an optional boolean argument to specify if the command should block
74
+ # the connection when the queue is empty. This argument defaults to false.
75
+ def pop(blocking = false)
76
+ if blocking
77
+ redis.brpop(name, TIMEOUT)[1] rescue nil
78
+ else
79
+ redis.rpop(name)
80
+ end
81
+ end
82
+
83
+ # Pushes items to the end of the queue.
84
+ def push(*items)
85
+ # Up until Redis 2.3, `rpush` accepts a single value.
86
+ if REDIS_VERSION < '2.3'
87
+ items.each { |item| redis.rpush(name, item) }
88
+ else
89
+ redis.rpush(name, items)
90
+ end
91
+ end
92
+ alias << push
93
+
94
+ # Retrieves the first queued item.
95
+ #
96
+ # Takes an optional boolean argument to specify if the command should block
97
+ # the connection when the queue is empty. This argument defaults to false.
98
+ def shift(blocking = false)
99
+ if blocking
100
+ redis.blpop(name, TIMEOUT)[1] rescue nil
101
+ else
102
+ redis.lpop(name)
103
+ end
104
+ end
105
+
106
+ # Pushes items to the front of the queue.
107
+ def unshift(*items)
108
+ # Up until Redis 2.3, `rpush` accepts a single value.
109
+ if REDIS_VERSION < '2.3'
110
+ items.each { |item| redis.lpush(name, item) }
111
+ else
112
+ redis.lpush(name, items)
113
+ end
114
+ end
115
+
116
+ private
117
+
118
+ def redis
119
+ Redis.current
120
+ end
121
+ end
@@ -0,0 +1,131 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'test/unit'
5
+
6
+ require File.expand_path('../lib/turnpike', File.dirname(__FILE__))
7
+
8
+ class TestTurnpike < Test::Unit::TestCase
9
+ def setup
10
+ Redis.current.flushall
11
+ end
12
+
13
+ def test_emptiness
14
+ queue = Turnpike.new
15
+ assert(queue.empty?)
16
+
17
+ queue << 1
18
+ assert(!queue.empty?)
19
+
20
+ queue.clear
21
+ assert(queue.empty?)
22
+ end
23
+
24
+ def test_pushing_items
25
+ queue = Turnpike.new
26
+ queue.push(1)
27
+ assert_equal(1, queue.length)
28
+
29
+ queue.push(2, 3)
30
+ assert_equal(3, queue.length)
31
+ assert_equal(['1', '2', '3'], queue.peek(0, 3))
32
+ end
33
+
34
+ def test_unshifting_items
35
+ queue = Turnpike.new
36
+ queue.unshift(1)
37
+ assert_equal(1, queue.length)
38
+
39
+ queue.unshift(2, 3)
40
+ assert_equal(3, queue.length)
41
+ assert_equal(['3', '2', '1'], queue.peek(0, 3))
42
+ end
43
+
44
+ def test_popping_items
45
+ queue = Turnpike.new
46
+ queue.push(1, 2)
47
+ assert_equal('2', queue.pop)
48
+ assert_equal('1', queue.pop)
49
+ assert_equal(nil, queue.pop)
50
+ end
51
+
52
+ def test_shifting_items
53
+ queue = Turnpike.new
54
+ queue.push(1, 2)
55
+ assert_equal('1', queue.shift)
56
+ assert_equal('2', queue.shift)
57
+ assert_equal(nil, queue.shift)
58
+ end
59
+
60
+ def test_enumeration
61
+ queue = Turnpike.new
62
+ queue.push(1, 2)
63
+ items = []
64
+ queue.each { |item| items << item }
65
+ assert_equal(['1', '2'], items)
66
+
67
+ queue.push(1, 2, 3, 4)
68
+ slices = []
69
+ queue.each_slice(3) { |slice| slices << slice }
70
+ assert_equal([['1', '2', '3'], ['4']], slices)
71
+
72
+ queue.push(1, 2)
73
+ slices = []
74
+ queue.each_slice(2) { |slice| slices << slice }
75
+ assert_equal([['1', '2']], slices)
76
+ end
77
+
78
+ def test_aliases
79
+ queue = Turnpike.new
80
+ queue << 1
81
+ assert_equal(1, queue.size)
82
+ end
83
+
84
+ def test_multiple_queues
85
+ queue1 = Turnpike.new("foo")
86
+ queue2 = Turnpike.new("bar")
87
+
88
+ queue1.push(1)
89
+ queue2.push(2, 3)
90
+
91
+ assert_equal(1, queue1.length)
92
+ assert_equal(2, queue2.length)
93
+ end
94
+
95
+ def test_blocking_pop
96
+ queue = Turnpike.new
97
+ started_at = Time.now.to_i
98
+ Thread.new do
99
+ sleep(1)
100
+ queue.push(1)
101
+ end
102
+ assert_equal(0, queue.length)
103
+ assert_equal('1', queue.pop(true))
104
+ assert_equal(1, Time.now.to_i - started_at)
105
+ end
106
+
107
+ def test_blocking_shift
108
+ queue = Turnpike.new
109
+ started_at = Time.now.to_i
110
+ Thread.new do
111
+ sleep(1)
112
+ queue.push(1)
113
+ end
114
+ assert_equal(0, queue.length)
115
+ assert_equal('1', queue.shift(true))
116
+ assert_equal(1, Time.now.to_i - started_at)
117
+ end
118
+
119
+ def test_timeout
120
+ queue = Turnpike.new
121
+ thread = Thread.new do
122
+ sleep(3)
123
+ queue.push(1)
124
+ end
125
+ assert_equal(0, queue.length)
126
+ assert_equal(nil, queue.shift(true))
127
+
128
+ thread.join
129
+ assert_equal(1, queue.length)
130
+ end
131
+ end
data/turnpike.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require "./lib/turnpike"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "turnpike"
6
+ s.version = Turnpike::VERSION
7
+ s.authors = ["Paper Cavalier"]
8
+ s.email = ["code@papercavalier.com"]
9
+ s.homepage = ""
10
+ s.summary = %q{Turnpike is a Redis-backed processing queue.}
11
+ s.description = %q{Turnpike is a Redis-backed processing queue.}
12
+
13
+ s.rubyforge_project = "turnpike"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ {
21
+ 'redis' => '~> 2.2'
22
+ }.each do |lib, version|
23
+ s.add_runtime_dependency lib, version
24
+ end
25
+
26
+ {
27
+ 'rake' => '~> 0.9'
28
+ }.each do |lib, version|
29
+ s.add_development_dependency lib, version
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: turnpike
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Paper Cavalier
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-07-15 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: redis
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 2
30
+ version: "2.2"
31
+ type: :runtime
32
+ prerelease: false
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rake
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 9
44
+ version: "0.9"
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *id002
48
+ description: Turnpike is a Redis-backed processing queue.
49
+ email:
50
+ - code@papercavalier.com
51
+ executables: []
52
+
53
+ extensions: []
54
+
55
+ extra_rdoc_files: []
56
+
57
+ files:
58
+ - .gitignore
59
+ - .rvmrc
60
+ - CHANGELOG.md
61
+ - Gemfile
62
+ - README.md
63
+ - Rakefile
64
+ - lib/turnpike.rb
65
+ - test/turnpike_test.rb
66
+ - turnpike.gemspec
67
+ has_rdoc: true
68
+ homepage: ""
69
+ licenses: []
70
+
71
+ post_install_message:
72
+ rdoc_options: []
73
+
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ hash: -65682769668407542
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: -65682769668407542
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ requirements: []
95
+
96
+ rubyforge_project: turnpike
97
+ rubygems_version: 1.3.7
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Turnpike is a Redis-backed processing queue.
101
+ test_files:
102
+ - test/turnpike_test.rb