redis-scheduler 0.7 → 0.8
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 +4 -4
- data/README +17 -15
- data/test/redis-scheduler.rb +118 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4c61ee6608f6112456f84933f3b209f879a3401
|
4
|
+
data.tar.gz: ae05d544a25078cd248a0e70ea005fca7df1e629
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce8cd9ee9ba8b78a436bb1e680cb7f34b6fb3bdb41907a4bb8825053371e286e8082935f768b1fe727b3b509848d1405c44a12aaffd7ad4ca99c4a189e40765a
|
7
|
+
data.tar.gz: 257cbd5324c02e216ee497a72ea4adbe3c9fa74d9795d7fd4143be41b3d186d08559883d969f29ce97837dd99e52a7bff0a2bd09f52e4197ace5122f7000b9e9
|
data/README
CHANGED
@@ -1,24 +1,22 @@
|
|
1
|
-
|
2
|
-
items to be processed at arbitrary points in
|
3
|
-
|
4
|
-
RedisScheduler#each).
|
1
|
+
A simple, production-ready chronological scheduler for Redis. It allows you to
|
2
|
+
schedule items to be processed at arbitrary points in the future, and easily
|
3
|
+
retrieve only those items that are due to be processed.
|
5
4
|
|
6
5
|
It does everything you'd expect from a production scheduler:
|
7
|
-
* You can schedule items at arbitrary times.
|
6
|
+
* You can schedule arbitrary items at arbitrary times.
|
8
7
|
* You can iterate over ready items in either blocking or non-blocking mode.
|
9
|
-
* It supports multiple
|
10
|
-
*
|
11
|
-
* Work items lost as part of
|
8
|
+
* It supports multiple concurrent producers and consumers.
|
9
|
+
* An application exception causes the item to be rescheduled at the original time.
|
10
|
+
* Work items lost as part of an application crash or segfault are recoverable.
|
12
11
|
|
13
|
-
In non-blocking mode
|
14
|
-
|
15
|
-
|
16
|
-
items
|
17
|
-
never return.
|
12
|
+
In non-blocking mode, RedisScheduler#each will iterate over only those items
|
13
|
+
whose scheduled time is less than or equal to the current time, and then stop.
|
14
|
+
In blocking mode, RedisScheduler#each will additionally wait until further
|
15
|
+
items are available. In nonblocking mode, #each will never return.
|
18
16
|
|
19
17
|
For debugging purposes, you can use RedisScheduler#items to iterate over all
|
20
|
-
items in the queue
|
21
|
-
|
18
|
+
items in the queue. Note that this method is not guaranteed to be consistent in
|
19
|
+
the presence of contemporaneous producers or consumers.
|
22
20
|
|
23
21
|
For error recovery purposes, you can use RedisScheduler#processing_set_items
|
24
22
|
to iterate over all the items in the processing set to determine whether any
|
@@ -41,6 +39,10 @@ of them are the result of a process crash.
|
|
41
39
|
20.06058172: c
|
42
40
|
... waits forever ...
|
43
41
|
|
42
|
+
== Documentation
|
43
|
+
|
44
|
+
See RedisScheduler's #initiatilize, schedule! and #each methods.
|
45
|
+
|
44
46
|
== Implementation
|
45
47
|
|
46
48
|
See http://masanjin.net/blog/using-redis-for-scheduling for some details.
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'redis'
|
3
|
+
require 'redis-scheduler'
|
4
|
+
require 'timecop'
|
5
|
+
|
6
|
+
## WARNING! This currently writes a bunch of keys to the Redis running on the
|
7
|
+
## default location. The keys are prefixed with
|
8
|
+
## "test-8ee2027983915ec78acc45027d874316/" and
|
9
|
+
## "test-8ee2027983915ec78acc45027d874317/" to avoid colliding with anything
|
10
|
+
## important, but this is not a great strategy, eh?
|
11
|
+
|
12
|
+
class RedisSchedulerTest < Minitest::Test
|
13
|
+
TIME = Time.local 2012, 1, 1, 15, 0, 0
|
14
|
+
|
15
|
+
def setup
|
16
|
+
super
|
17
|
+
@redis = Redis.new
|
18
|
+
@scheduler = RedisScheduler.new @redis, namespace: "test-8ee2027983915ec78acc45027d874316/", blocking: false
|
19
|
+
@uniq_scheduler = RedisScheduler.new @redis, namespace: "test-8ee2027983915ec78acc45027d874317/", blocking: false, uniq: true
|
20
|
+
end
|
21
|
+
|
22
|
+
def teardown
|
23
|
+
super
|
24
|
+
@scheduler.reset!
|
25
|
+
@uniq_scheduler.reset!
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_begins_empty
|
29
|
+
assert_equal 0, @scheduler.size
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_stuff_waits
|
33
|
+
Timecop.freeze TIME do
|
34
|
+
@scheduler.schedule! "a", (TIME + 100)
|
35
|
+
got_item = false
|
36
|
+
@scheduler.each { got_item = true }
|
37
|
+
assert !got_item
|
38
|
+
end
|
39
|
+
|
40
|
+
Timecop.freeze(TIME + 50) do
|
41
|
+
got_item = false
|
42
|
+
@scheduler.each { got_item = true }
|
43
|
+
assert !got_item
|
44
|
+
end
|
45
|
+
|
46
|
+
Timecop.freeze(TIME + 100) do
|
47
|
+
got_item = false
|
48
|
+
@scheduler.each { got_item = true }
|
49
|
+
assert got_item
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_can_get_items_later_than_their_timestamp
|
54
|
+
Timecop.freeze TIME do
|
55
|
+
@scheduler.schedule! "a", (TIME + 100)
|
56
|
+
end
|
57
|
+
|
58
|
+
Timecop.freeze(TIME + 200) do
|
59
|
+
got_item = false
|
60
|
+
@scheduler.each { got_item = true }
|
61
|
+
assert got_item
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_ordering_is_based_on_timestamp
|
66
|
+
Timecop.freeze TIME do
|
67
|
+
@scheduler.schedule! "b", (TIME + 101)
|
68
|
+
@scheduler.schedule! "a", (TIME + 100)
|
69
|
+
|
70
|
+
el, ts = @scheduler.items[0]
|
71
|
+
assert_equal "a", el
|
72
|
+
assert_equal TIME + 100, ts
|
73
|
+
|
74
|
+
el, ts = @scheduler.items[1]
|
75
|
+
assert_equal "b", el
|
76
|
+
assert_equal TIME + 101, ts
|
77
|
+
|
78
|
+
assert_equal [["a", TIME + 100], ["b", TIME + 101]], @scheduler.items[0, 2]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_can_schedule_same_item_multiple_times
|
83
|
+
Timecop.freeze TIME do
|
84
|
+
@scheduler.schedule! "a", (TIME + 101)
|
85
|
+
@scheduler.schedule! "a", (TIME + 100)
|
86
|
+
|
87
|
+
assert_equal [["a", TIME + 100], ["a", TIME + 101]], @scheduler.items[0, 2]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_uniq_schedules_update_items_rather_than_representing_them_multiple_times
|
92
|
+
Timecop.freeze TIME do
|
93
|
+
@uniq_scheduler.schedule! "a", (TIME + 101)
|
94
|
+
@uniq_scheduler.schedule! "a", (TIME + 100)
|
95
|
+
|
96
|
+
assert_equal [["a", TIME + 100]], @uniq_scheduler.items[0, 2]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_oldest_always_wins
|
101
|
+
Timecop.freeze TIME do
|
102
|
+
@scheduler.schedule! "a", (TIME + 101)
|
103
|
+
end
|
104
|
+
|
105
|
+
Timecop.freeze(TIME + 50) do
|
106
|
+
@scheduler.schedule! "b", (TIME + 100)
|
107
|
+
end
|
108
|
+
|
109
|
+
Timecop.freeze(TIME + 200) do
|
110
|
+
items = []
|
111
|
+
@scheduler.each do |item, ts|
|
112
|
+
items << item
|
113
|
+
end
|
114
|
+
|
115
|
+
assert_equal ["b", "a"], items
|
116
|
+
end
|
117
|
+
end
|
118
|
+
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.8'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Morgan
|
@@ -10,9 +10,9 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2014-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
14
|
-
|
15
|
-
|
13
|
+
description: |-
|
14
|
+
A simple, production-ready chronological scheduler for Redis. It allows you to schedule items to be processed at arbitrary points in the future, and easily
|
15
|
+
retrieve only those items that are due to be processed.
|
16
16
|
email: wmorgan-redis-scheduler@masanjin.net
|
17
17
|
executables: []
|
18
18
|
extensions: []
|
@@ -21,6 +21,7 @@ files:
|
|
21
21
|
- README
|
22
22
|
- COPYING
|
23
23
|
- lib/redis-scheduler.rb
|
24
|
+
- test/redis-scheduler.rb
|
24
25
|
homepage: http://gitub.com/wmorgan/redis-scheduler
|
25
26
|
licenses: []
|
26
27
|
metadata: {}
|