em-resque 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +7 -1
- data/lib/em-resque.rb +3 -14
- data/lib/em-resque/version.rb +1 -1
- data/lib/em-resque/worker.rb +73 -0
- data/lib/em-resque/worker_machine.rb +17 -6
- data/test/worker_test.rb +15 -9
- metadata +11 -11
data/README.markdown
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
THIS FORK
|
2
|
+
=========
|
3
|
+
|
4
|
+
This fork is intended to only run one fiber and does not use Fiber yielding to pick up jobs. This fork was created
|
5
|
+
because the EM::Synchrony.sleep solution does not work well for sending Apple Push Notifications.
|
6
|
+
|
1
7
|
EM::Resque
|
2
8
|
==========
|
3
9
|
|
@@ -216,7 +222,7 @@ given a string or a Redis object. This means if you're already using
|
|
216
222
|
Redis in your app, EM::Resquec an re-use the existing connection.
|
217
223
|
EM::Resque is using the non-blocking em-redis when given the host as a
|
218
224
|
string. If using a Redis object, please use the non-blocking
|
219
|
-
EM::
|
225
|
+
EM::Hiredis.
|
220
226
|
|
221
227
|
String: `EM::Resque::WorkerMachine.new(opts.merge(:redis => 'localhost:6379'))`
|
222
228
|
|
data/lib/em-resque.rb
CHANGED
@@ -1,28 +1,17 @@
|
|
1
1
|
require 'resque'
|
2
2
|
require 'em-synchrony'
|
3
|
-
require 'em-
|
3
|
+
require 'em-hiredis'
|
4
4
|
require 'em-synchrony/connection_pool'
|
5
5
|
require 'uri'
|
6
6
|
|
7
7
|
module EM::Resque
|
8
8
|
extend Resque
|
9
9
|
|
10
|
-
def self.initialize_redis(server, pool_size = 1)
|
10
|
+
def self.initialize_redis(server, namespace = :resque, pool_size = 1)
|
11
11
|
case server
|
12
12
|
when String
|
13
|
-
opts = if server =~ /redis\:\/\//
|
14
|
-
uri = URI.parse(server)
|
15
|
-
{:host => uri.host, :port => uri.port}
|
16
|
-
else
|
17
|
-
server, namespace = server.split('/', 2)
|
18
|
-
host, port, db = server.split(':')
|
19
|
-
{:host => host, :port => port, :thread_safe => true, :db => db}
|
20
|
-
end
|
21
|
-
|
22
|
-
namespace ||= :resque
|
23
|
-
|
24
13
|
redis = EventMachine::Synchrony::ConnectionPool.new(:size => pool_size) do
|
25
|
-
EM::
|
14
|
+
EM::Hiredis.connect(server)
|
26
15
|
end
|
27
16
|
|
28
17
|
Resque.redis = Redis::Namespace.new(namespace, :redis => redis)
|
data/lib/em-resque/version.rb
CHANGED
data/lib/em-resque/worker.rb
CHANGED
@@ -3,10 +3,83 @@ require 'resque'
|
|
3
3
|
# A non-forking version of Resque worker, which handles waiting with
|
4
4
|
# a non-blocking version of sleep.
|
5
5
|
class EventMachine::Resque::Worker < Resque::Worker
|
6
|
+
attr_accessor :tick_instead_of_sleep
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
super(*args)
|
10
|
+
self.tick_instead_of_sleep = false
|
11
|
+
end
|
12
|
+
|
6
13
|
# Overwrite system sleep with the non-blocking version
|
7
14
|
def sleep(interval)
|
8
15
|
EM::Synchrony.sleep interval
|
9
16
|
end
|
17
|
+
|
18
|
+
# Overwrite Resque's #work method to allow us to determine whether or not we want to ticks through a reactor
|
19
|
+
# instead of using EM::Synchrony sleep.
|
20
|
+
#
|
21
|
+
# The reason for this option is because when sending push notifications and using 1 fiber, the response from Apple
|
22
|
+
# will come after another job has been finished and is generally unreliable. Note that this means that you can't use
|
23
|
+
# this worker with more than one fiber for push workers.
|
24
|
+
def work(interval = 5.0, &block)
|
25
|
+
if self.tick_instead_of_sleep
|
26
|
+
work_tick(interval, &block)
|
27
|
+
else
|
28
|
+
super(interval, &block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Resque::Worker's #work method modified to use EM.next_tick instead of sleep
|
33
|
+
def work_tick(interval, &block)
|
34
|
+
interval = Float(interval)
|
35
|
+
$0 = "resque: Starting"
|
36
|
+
startup
|
37
|
+
|
38
|
+
work_loop = lambda do
|
39
|
+
if shutdown?
|
40
|
+
unregister_worker
|
41
|
+
EM.stop
|
42
|
+
next
|
43
|
+
end
|
44
|
+
|
45
|
+
if not paused? and job = reserve
|
46
|
+
log "got: #{job.inspect}"
|
47
|
+
job.worker = self
|
48
|
+
run_hook :before_fork, job
|
49
|
+
working_on job
|
50
|
+
|
51
|
+
if @child = fork
|
52
|
+
srand # Reseeding
|
53
|
+
procline "Forked #{@child} at #{Time.now.to_i}"
|
54
|
+
begin
|
55
|
+
Process.waitpid(@child)
|
56
|
+
rescue SystemCallError
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
else
|
60
|
+
unregister_signal_handlers if !@cant_fork && term_child
|
61
|
+
procline "Processing #{job.queue} since #{Time.now.to_i}"
|
62
|
+
redis.client.reconnect # Don't share connection with parent
|
63
|
+
perform(job, &block)
|
64
|
+
exit! unless @cant_fork
|
65
|
+
EM::Timer.new(interval) do
|
66
|
+
EM.next_tick(&work_loop)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
done_working
|
71
|
+
@child = nil
|
72
|
+
else
|
73
|
+
break if interval.zero?
|
74
|
+
log! "Sleeping for #{interval} seconds"
|
75
|
+
procline paused? ? "Paused" : "Waiting for #{@queues.join(',')}"
|
76
|
+
EM::Timer.new(interval) do
|
77
|
+
EM.next_tick(&work_loop)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
EM.next_tick(&work_loop)
|
82
|
+
end
|
10
83
|
|
11
84
|
# Be sure we're never forking
|
12
85
|
def fork
|
@@ -16,24 +16,30 @@ module EventMachine
|
|
16
16
|
# signals and prunes dead workers
|
17
17
|
#
|
18
18
|
# == Options
|
19
|
-
#
|
19
|
+
# fibers:: The number of fibers to use in the worker (default 1)
|
20
20
|
# interval:: Time in seconds how often the workers check for new work
|
21
21
|
# (default 5)
|
22
|
-
# fibers_count:: How many fibers (and workers) to be run inside the
|
23
|
-
# machine (default 1)
|
24
22
|
# queues:: Which queues to poll (default all)
|
25
23
|
# verbose:: Verbose log output (default false)
|
26
24
|
# vverbose:: Even more verbose log output (default false)
|
27
25
|
# pidfile:: The file to save the process id number
|
26
|
+
# tick_instead_of_sleep:: Whether to tick through the reactor polling for jobs or use EM::Synchrony.sleep.
|
27
|
+
# Note that if you use this option, you'll be limited to 1 fiber.
|
28
28
|
def initialize(opts = {})
|
29
|
-
@concurrency = opts[:concurrency] || 20
|
30
29
|
@interval = opts[:interval] || 5
|
31
30
|
@fibers_count = opts[:fibers] || 1
|
32
31
|
@queues = opts[:queue] || opts[:queues] || '*'
|
33
32
|
@verbose = opts[:logging] || opts[:verbose] || false
|
34
33
|
@very_verbose = opts[:vverbose] || false
|
35
34
|
@pidfile = opts[:pidfile]
|
35
|
+
@redis_namespace = opts[:namespace] || :resque
|
36
36
|
@redis_uri = opts[:redis] || "redis://127.0.0.1:6379"
|
37
|
+
@tick_instead_of_sleep = !opts[:tick_instead_of_sleep].nil? ? opts[:tick_instead_of_sleep] : false
|
38
|
+
|
39
|
+
# If we're ticking instead of sleeping, we can only have one fiber
|
40
|
+
if @tick_instead_of_sleep
|
41
|
+
@fibers_count = 1
|
42
|
+
end
|
37
43
|
|
38
44
|
raise(ArgumentError, "Should have at least one fiber") if @fibers_count.to_i < 1
|
39
45
|
|
@@ -45,11 +51,15 @@ module EventMachine
|
|
45
51
|
# Start the machine and start polling queues.
|
46
52
|
def start
|
47
53
|
EM.synchrony do
|
48
|
-
EM::Resque.initialize_redis(@redis_uri, @fibers_count)
|
54
|
+
EM::Resque.initialize_redis(@redis_uri, @redis_namespace, @fibers_count)
|
49
55
|
trap_signals
|
50
56
|
prune_dead_workers
|
51
57
|
@fibers.each(&:resume)
|
52
|
-
|
58
|
+
|
59
|
+
# If we're ticking and not sleeping, we don't need to monitor for yielding
|
60
|
+
unless @tick_instead_of_sleep
|
61
|
+
system_monitor.resume
|
62
|
+
end
|
53
63
|
end
|
54
64
|
end
|
55
65
|
|
@@ -76,6 +86,7 @@ module EventMachine
|
|
76
86
|
worker = EM::Resque::Worker.new(*queues)
|
77
87
|
worker.verbose = @verbose
|
78
88
|
worker.very_verbose = @very_verbose
|
89
|
+
worker.tick_instead_of_sleep = @tick_instead_of_sleep
|
79
90
|
|
80
91
|
worker
|
81
92
|
end
|
data/test/worker_test.rb
CHANGED
@@ -12,10 +12,12 @@ context "Worker" do
|
|
12
12
|
worker = EM::Resque::Worker.new('*')
|
13
13
|
worker.work(0)
|
14
14
|
|
15
|
-
|
15
|
+
EM::Timer.new(0.5) do
|
16
|
+
assert_equal 1, EM::Resque.info[:processed]
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
worker.shutdown!
|
19
|
+
EM.stop
|
20
|
+
end
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
@@ -25,10 +27,12 @@ context "Worker" do
|
|
25
27
|
worker = EM::Resque::Worker.new('*')
|
26
28
|
worker.work(0)
|
27
29
|
|
28
|
-
|
30
|
+
EM::Timer.new(0.5) do
|
31
|
+
assert_equal 1, EM::Resque.redis.get("stat:processed_jobs").to_i
|
29
32
|
|
30
|
-
|
31
|
-
|
33
|
+
worker.shutdown!
|
34
|
+
EM.stop
|
35
|
+
end
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
@@ -38,9 +42,11 @@ context "Worker" do
|
|
38
42
|
worker = EM::Resque::Worker.new('*')
|
39
43
|
worker.work(0)
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
45
|
+
EM::Timer.new(0.5) do
|
46
|
+
assert_equal 1, Resque::Failure.count
|
47
|
+
worker.shutdown!
|
48
|
+
EM.stop
|
49
|
+
end
|
44
50
|
end
|
45
51
|
end
|
46
52
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-resque
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
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-
|
12
|
+
date: 2012-09-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: resque
|
@@ -44,13 +44,13 @@ dependencies:
|
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 1.0.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
-
name: em-
|
47
|
+
name: em-hiredis
|
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.
|
53
|
+
version: 0.1.0
|
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.
|
61
|
+
version: 0.1.0
|
62
62
|
description: ! " Em-resque is a version of Resque, which offers non-blocking and
|
63
63
|
non-forking\n workers. The idea is to have fast as possible workers for tasks
|
64
64
|
with lots of\n IO like pinging third party servers or hitting the database.\n\n
|
@@ -82,20 +82,20 @@ files:
|
|
82
82
|
- Rakefile
|
83
83
|
- LICENSE
|
84
84
|
- HISTORY.md
|
85
|
-
- lib/em-resque
|
85
|
+
- lib/em-resque.rb
|
86
|
+
- lib/em-resque/task_helper.rb
|
86
87
|
- lib/em-resque/worker.rb
|
87
|
-
- lib/em-resque/
|
88
|
+
- lib/em-resque/version.rb
|
88
89
|
- lib/em-resque/worker_machine.rb
|
89
|
-
- lib/em-resque/
|
90
|
+
- lib/em-resque/tasks.rb
|
90
91
|
- lib/tasks/em-resque.rake
|
91
|
-
- lib/em-resque.rb
|
92
92
|
- test/worker_machine_test.rb
|
93
|
+
- test/redis-test-cluster.conf
|
93
94
|
- test/em-resque_test.rb
|
94
|
-
- test/redis-test.conf
|
95
95
|
- test/task_helpers_test.rb
|
96
|
-
- test/redis-test-cluster.conf
|
97
96
|
- test/worker_test.rb
|
98
97
|
- test/test_helper.rb
|
98
|
+
- test/redis-test.conf
|
99
99
|
homepage: http://github.com/SponsorPay/em-resque
|
100
100
|
licenses: []
|
101
101
|
post_install_message:
|