redis-scheduler 0.2 → 0.3
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 +8 -3
- data/lib/redis-scheduler.rb +45 -7
- metadata +3 -5
data/README
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
This is a basic chronological scheduler for Redis. It allows you to schedule
|
2
2
|
items to be processed at arbitrary points in time (via #schedule!), and then
|
3
|
-
to easily retrieve only those items that are due to be processed (via #each
|
3
|
+
to easily retrieve only those items that are due to be processed (via #each).
|
4
|
+
|
4
5
|
Items are represented as strings.
|
5
6
|
|
6
7
|
It does everything you'd want from a production scheduler:
|
7
|
-
* You can schedule
|
8
|
+
* You can schedule items at arbitrary times.
|
8
9
|
* It supports multiple simultaneous readers and writers.
|
9
10
|
* An exception causes the in-process item to be rescheduled at the original time.
|
10
|
-
* A crash leaves the item in
|
11
|
+
* A crash leaves the item in a separate error queue, from which it can later be recovered.
|
11
12
|
* You can iterate over ready items in either blocking or non-blocking mode.
|
12
13
|
|
13
14
|
In non-blocking mode (the default), #each will iterate only over those work items
|
@@ -32,6 +33,10 @@ until items are available. In blocking mode, #each will never return.
|
|
32
33
|
20.06058172: c
|
33
34
|
... waits forever ...
|
34
35
|
|
36
|
+
== Implementation
|
37
|
+
|
38
|
+
See http://masanjin.net/blog/using-redis-for-scheduling for some details.
|
39
|
+
|
35
40
|
== Bug reports
|
36
41
|
|
37
42
|
Please file bugs here: https://github.com/wmorgan/redis-scheduler/issues
|
data/lib/redis-scheduler.rb
CHANGED
@@ -5,9 +5,8 @@ class RedisScheduler
|
|
5
5
|
CAS_DELAY = 0.5 # seconds
|
6
6
|
|
7
7
|
## options:
|
8
|
-
##
|
9
|
-
##
|
10
|
-
## there are items to be processed immediately.
|
8
|
+
## * +namespace+: prefix for redis data, e.g. "scheduler/"
|
9
|
+
## * +blocking+: whether #each should block or return immediately if there are items to be processed immediately.
|
11
10
|
##
|
12
11
|
## Note that nonblocking mode may still actually block as part of the
|
13
12
|
## check-and-set semantics, i.e. block during contention from multiple
|
@@ -35,6 +34,9 @@ class RedisScheduler
|
|
35
34
|
[@queue, @error_queue, @counter].each { |k| @redis.del k }
|
36
35
|
end
|
37
36
|
|
37
|
+
def size; @redis.zcard @queue end
|
38
|
+
def error_queue_size; @redis.llen @error_queue end
|
39
|
+
|
38
40
|
## yields items along with their scheduled times. only returns items
|
39
41
|
## on or after their scheduled times. items returned as strings. if
|
40
42
|
## @blocking is false, will stop once there are no more items that can
|
@@ -42,18 +44,27 @@ class RedisScheduler
|
|
42
44
|
## become available (and never terminate).
|
43
45
|
def each
|
44
46
|
while(x = get)
|
45
|
-
item, at = x
|
47
|
+
item, erritem, at = x
|
46
48
|
begin
|
47
49
|
yield item, at
|
48
50
|
rescue Exception # back in the hole!
|
49
51
|
schedule! item, at
|
50
52
|
raise
|
51
53
|
ensure
|
52
|
-
cleanup!
|
54
|
+
cleanup! erritem
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
59
|
+
## returns an Enumerable of [item, schedule time] pairs, which can be used to
|
60
|
+
## easily iterate over all the items in the queue, in order of earliest- to
|
61
|
+
## latest-scheduled. note that this view is not coordinated with write
|
62
|
+
## operations, and may be inconsistent (e.g. return duplicates, miss items,
|
63
|
+
## etc).
|
64
|
+
##
|
65
|
+
## for these reasons, this operation is mainly useful for debugging purposes.
|
66
|
+
def items; ItemEnumerator.new(@redis, @queue) end
|
67
|
+
|
57
68
|
private
|
58
69
|
|
59
70
|
def get; @blocking ? blocking_get : nonblocking_get end
|
@@ -78,8 +89,8 @@ private
|
|
78
89
|
throw :cas_retry
|
79
90
|
end
|
80
91
|
item =~ /^\d+:(\S+)$/ or raise InvalidEntryException, item
|
81
|
-
|
82
|
-
[item, Time.at(at.to_f)]
|
92
|
+
original = $1
|
93
|
+
[original, item, Time.at(at.to_f)]
|
83
94
|
end
|
84
95
|
end
|
85
96
|
end
|
@@ -87,4 +98,31 @@ private
|
|
87
98
|
def cleanup! item
|
88
99
|
@redis.lrem @error_queue, 1, item
|
89
100
|
end
|
101
|
+
|
102
|
+
## enumerable for just iterating over everything in the queue
|
103
|
+
class ItemEnumerator
|
104
|
+
include Enumerable
|
105
|
+
def initialize redis, q
|
106
|
+
@redis = redis
|
107
|
+
@q = q
|
108
|
+
end
|
109
|
+
|
110
|
+
BLOCK_SIZE = 10
|
111
|
+
def each
|
112
|
+
start = 0
|
113
|
+
while start < size
|
114
|
+
elements = @redis.zrange @q, start, start + BLOCK_SIZE,
|
115
|
+
:withscores => true
|
116
|
+
elements.each_slice(2) do |item, at| # isgh
|
117
|
+
item =~ /^\d+:(\S+)$/ or raise InvalidEntryException, item
|
118
|
+
item = $1
|
119
|
+
yield item, Time.at(at.to_f)
|
120
|
+
end
|
121
|
+
start += elements.size
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def size; @redis.zcard @q end
|
126
|
+
end
|
127
|
+
|
90
128
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
13
|
-
default_executable:
|
12
|
+
date: 2012-04-29 00:00:00.000000000 Z
|
14
13
|
dependencies: []
|
15
14
|
description: A basic chronological scheduler for Redis. Add work items to be processed
|
16
15
|
at specific times in the future, and easily retrieve all items that are ready for
|
@@ -23,7 +22,6 @@ files:
|
|
23
22
|
- README
|
24
23
|
- COPYING
|
25
24
|
- lib/redis-scheduler.rb
|
26
|
-
has_rdoc: true
|
27
25
|
homepage: http://gitub.com/wmorgan/redis-scheduler
|
28
26
|
licenses: []
|
29
27
|
post_install_message:
|
@@ -48,7 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
48
46
|
version: '0'
|
49
47
|
requirements: []
|
50
48
|
rubyforge_project:
|
51
|
-
rubygems_version: 1.
|
49
|
+
rubygems_version: 1.8.11
|
52
50
|
signing_key:
|
53
51
|
specification_version: 3
|
54
52
|
summary: A basic chronological scheduler for Redis.
|