derfred-workling 0.4.9.2 → 0.4.9.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/bin/workling_client +9 -7
- data/{script → contrib}/bj_invoker.rb +0 -0
- data/{script → contrib}/starling_status.rb +0 -0
- data/lib/{cattr_accessor.rb → extensions/cattr_accessor.rb} +0 -0
- data/lib/{mattr_accessor.rb → extensions/mattr_accessor.rb} +0 -0
- data/lib/workling.rb +98 -94
- data/lib/workling/base.rb +6 -11
- data/lib/workling/clients/amqp_client.rb +13 -5
- data/lib/workling/clients/amqp_exchange_client.rb +19 -11
- data/lib/workling/clients/backgroundjob_client.rb +25 -0
- data/lib/workling/clients/base.rb +40 -8
- data/lib/workling/clients/broker_base.rb +63 -0
- data/lib/workling/clients/memcache_queue_client.rb +24 -12
- data/lib/workling/clients/memory_queue_client.rb +34 -0
- data/lib/workling/clients/not_client.rb +14 -0
- data/lib/workling/clients/not_remote_client.rb +17 -0
- data/lib/workling/clients/spawn_client.rb +47 -0
- data/lib/workling/clients/sqs_client.rb +9 -8
- data/lib/workling/clients/thread_client.rb +18 -0
- data/lib/workling/clients/xmpp_client.rb +14 -4
- data/lib/workling/discovery.rb +1 -1
- data/lib/workling/invokers/amqp_single_subscriber.rb +42 -0
- data/lib/workling/invokers/base.rb +124 -0
- data/lib/workling/invokers/basic_poller.rb +38 -0
- data/lib/workling/invokers/eventmachine_subscriber.rb +38 -0
- data/lib/workling/invokers/looped_subscriber.rb +34 -0
- data/lib/workling/invokers/thread_pool_poller.rb +165 -0
- data/lib/workling/invokers/threaded_poller.rb +149 -0
- data/lib/workling/remote.rb +10 -41
- data/lib/workling/return/store/base.rb +7 -7
- data/lib/workling/return/store/memory_return_store.rb +0 -2
- data/lib/workling/return/store/starling_return_store.rb +7 -8
- data/lib/workling/routing/base.rb +1 -4
- data/lib/workling/routing/class_and_method_routing.rb +0 -2
- data/lib/workling/routing/static_routing.rb +0 -4
- data/lib/{workling_server.rb → workling_daemon.rb} +27 -25
- metadata +21 -28
- data/lib/rude_q/client.rb +0 -11
- data/lib/workling/remote/invokers/amqp_single_subscriber.rb +0 -45
- data/lib/workling/remote/invokers/base.rb +0 -124
- data/lib/workling/remote/invokers/basic_poller.rb +0 -41
- data/lib/workling/remote/invokers/eventmachine_subscriber.rb +0 -41
- data/lib/workling/remote/invokers/looped_subscriber.rb +0 -38
- data/lib/workling/remote/invokers/thread_pool_poller.rb +0 -169
- data/lib/workling/remote/invokers/threaded_poller.rb +0 -153
- data/lib/workling/remote/runners/amqp_exchange_runner.rb +0 -45
- data/lib/workling/remote/runners/backgroundjob_runner.rb +0 -35
- data/lib/workling/remote/runners/base.rb +0 -42
- data/lib/workling/remote/runners/client_runner.rb +0 -46
- data/lib/workling/remote/runners/not_remote_runner.rb +0 -23
- data/lib/workling/remote/runners/not_runner.rb +0 -17
- data/lib/workling/remote/runners/rudeq_runner.rb +0 -23
- data/lib/workling/remote/runners/spawn_runner.rb +0 -38
- data/lib/workling/remote/runners/starling_runner.rb +0 -13
- data/lib/workling/return/store/rudeq_return_store.rb +0 -24
- data/lib/workling/rudeq.rb +0 -7
- data/lib/workling/rudeq/client.rb +0 -17
- data/lib/workling/rudeq/poller.rb +0 -116
@@ -1,5 +1,7 @@
|
|
1
1
|
#
|
2
|
-
# Clients are responsible for
|
2
|
+
# Clients are responsible for dispatching jobs either to a broker (starling, rabbitmq etc) or invoke them (spawn)
|
3
|
+
#
|
4
|
+
# Clients that involve a broker should subclass Workling::Clients::BrokerBase
|
3
5
|
#
|
4
6
|
# Clients are used to request jobs on a broker, get results for a job from a broker, and subscribe to results
|
5
7
|
# from a specific type of job.
|
@@ -8,9 +10,39 @@ module Workling
|
|
8
10
|
module Clients
|
9
11
|
class Base
|
10
12
|
|
13
|
+
#
|
14
|
+
# Load the required libraries, for this client
|
15
|
+
#
|
16
|
+
def self.load
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
#
|
22
|
+
# See if the libraries required for this client are installed
|
23
|
+
#
|
24
|
+
def self.installed?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
|
11
29
|
# returns the Workling::Base.logger
|
12
30
|
def logger; Workling::Base.logger; end
|
13
31
|
|
32
|
+
|
33
|
+
#
|
34
|
+
# Dispatch a job to the client. If this client uses a job broker, then
|
35
|
+
# this method should submit it, otherwise it should run the job
|
36
|
+
#
|
37
|
+
# clazz: Name of the worker class
|
38
|
+
# method: Name of the methods on the worker
|
39
|
+
# options: optional arguments for the job
|
40
|
+
#
|
41
|
+
def dispatch(clazz, method, options = {})
|
42
|
+
raise NotImplementedError.new("Implement dispatch(clazz, method, options) in your client. ")
|
43
|
+
end
|
44
|
+
|
45
|
+
|
14
46
|
#
|
15
47
|
# Requests a job on the broker.
|
16
48
|
#
|
@@ -18,8 +50,8 @@ module Workling
|
|
18
50
|
# arguments: the argument to the worker method
|
19
51
|
#
|
20
52
|
def request(work_type, arguments)
|
21
|
-
raise
|
22
|
-
end
|
53
|
+
raise WorklingError.new("This client does not involve a broker.")
|
54
|
+
end
|
23
55
|
|
24
56
|
#
|
25
57
|
# Gets job results off a job broker. Returns nil if there are no results.
|
@@ -27,7 +59,7 @@ module Workling
|
|
27
59
|
# worker_uid: the uid returned by workling when the work was dispatched
|
28
60
|
#
|
29
61
|
def retrieve(work_uid)
|
30
|
-
raise
|
62
|
+
raise WorklingError.new("This client does not involve a broker.")
|
31
63
|
end
|
32
64
|
|
33
65
|
#
|
@@ -36,22 +68,22 @@ module Workling
|
|
36
68
|
# worker_type:
|
37
69
|
#
|
38
70
|
def subscribe(work_type)
|
39
|
-
raise
|
71
|
+
raise WorklingError.new("This client does not involve a broker.")
|
40
72
|
end
|
41
73
|
|
42
74
|
#
|
43
75
|
# Opens a connection to the job broker.
|
44
76
|
#
|
45
77
|
def connect
|
46
|
-
raise
|
78
|
+
raise WorklingError.new("This client does not involve a broker.")
|
47
79
|
end
|
48
80
|
|
49
81
|
#
|
50
82
|
# Closes the connection to the job broker.
|
51
83
|
#
|
52
84
|
def close
|
53
|
-
raise
|
85
|
+
raise WorklingError.new("This client does not involve a broker.")
|
54
86
|
end
|
55
87
|
end
|
56
88
|
end
|
57
|
-
end
|
89
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Workling
|
2
|
+
module Clients
|
3
|
+
class BrokerBase < Base
|
4
|
+
|
5
|
+
#
|
6
|
+
# Dispatch a job to the client. If this client uses a job broker, then
|
7
|
+
# this method should submit it, otherwise it should run the job
|
8
|
+
#
|
9
|
+
# clazz: Name of the worker class
|
10
|
+
# method: Name of the methods on the worker
|
11
|
+
# options: optional arguments for the job
|
12
|
+
#
|
13
|
+
def dispatch(clazz, method, options = {})
|
14
|
+
@connected ||= connect
|
15
|
+
request(Workling::Remote.routing.queue_for(clazz, method), options)
|
16
|
+
return nil
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# Requests a job on the broker.
|
22
|
+
#
|
23
|
+
# work_type:
|
24
|
+
# arguments: the argument to the worker method
|
25
|
+
#
|
26
|
+
def request(work_type, arguments)
|
27
|
+
raise NotImplementedError.new("Implement request(work_type, arguments) in your client. ")
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Gets job results off a job broker. Returns nil if there are no results.
|
32
|
+
#
|
33
|
+
# worker_uid: the uid returned by workling when the work was dispatched
|
34
|
+
#
|
35
|
+
def retrieve(work_uid)
|
36
|
+
raise NotImplementedError.new("Implement retrieve(work_uid) in your client. ")
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Subscribe to job results in a job broker.
|
41
|
+
#
|
42
|
+
# worker_type:
|
43
|
+
#
|
44
|
+
def subscribe(work_type)
|
45
|
+
raise NotImplementedError.new("Implement subscribe(work_type) in your client. ")
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Opens a connection to the job broker.
|
50
|
+
#
|
51
|
+
def connect
|
52
|
+
raise NotImplementedError.new("Implement connect() in your client. ")
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Closes the connection to the job broker.
|
57
|
+
#
|
58
|
+
def close
|
59
|
+
raise NotImplementedError.new("Implement close() in your client. ")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'workling/clients/base'
|
2
|
-
require 'memcache'
|
3
|
-
|
4
1
|
#
|
5
2
|
# This client can be used for all Queue Servers that speak Memcached, such as Starling.
|
6
3
|
#
|
@@ -12,12 +9,26 @@ require 'memcache'
|
|
12
9
|
#
|
13
10
|
module Workling
|
14
11
|
module Clients
|
15
|
-
class MemcacheQueueClient < Workling::Clients::
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
12
|
+
class MemcacheQueueClient < Workling::Clients::BrokerBase
|
13
|
+
|
14
|
+
def self.installed?
|
15
|
+
begin
|
16
|
+
require 'starling'
|
17
|
+
rescue LoadError
|
18
|
+
end
|
19
|
+
|
20
|
+
Object.const_defined? "Starling"
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.load
|
24
|
+
begin
|
25
|
+
gem 'memcache-client'
|
26
|
+
require 'memcache'
|
27
|
+
rescue Gem::LoadError
|
28
|
+
Workling::Base.logger.info "WORKLING: couldn't find memcache-client. Install: \"gem install memcache-client\". "
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
21
32
|
# the url with which the memcache client expects to reach starling
|
22
33
|
attr_accessor :queueserver_urls
|
23
34
|
|
@@ -35,11 +46,11 @@ module Workling
|
|
35
46
|
def connect
|
36
47
|
@queueserver_urls = Workling.config[:listens_on].split(',').map { |url| url ? url.strip : url }
|
37
48
|
options = [@queueserver_urls, Workling.config[:memcache_options]].compact
|
38
|
-
self.connection =
|
39
|
-
|
49
|
+
self.connection = ::MemCache.new(*options)
|
50
|
+
|
40
51
|
raise_unless_connected!
|
41
52
|
end
|
42
|
-
|
53
|
+
|
43
54
|
# closes the memcache connection
|
44
55
|
def close
|
45
56
|
self.connection.flush_all
|
@@ -86,6 +97,7 @@ module Workling
|
|
86
97
|
raise Workling::WorklingConnectionError.new("#{e.class.to_s} - #{e.message}")
|
87
98
|
end
|
88
99
|
end
|
100
|
+
|
89
101
|
end
|
90
102
|
end
|
91
103
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Workling
|
2
|
+
module Clients
|
3
|
+
class MemoryQueueClient < Workling::Clients::BrokerBase
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@subscribers ||= {}
|
7
|
+
@queues ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
# collects the worker blocks in a hash
|
11
|
+
def subscribe(work_type, &block)
|
12
|
+
@subscribers[work_type] = block
|
13
|
+
end
|
14
|
+
|
15
|
+
# immediately invokes the required worker block
|
16
|
+
def request(work_type, arguments)
|
17
|
+
if subscription = @subscribers[work_type]
|
18
|
+
subscription.call(arguments)
|
19
|
+
else
|
20
|
+
@queues[work_type] ||= []
|
21
|
+
@queues[work_type] << arguments
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def retrieve(work_type)
|
26
|
+
queue = @queues[work_type]
|
27
|
+
queue.pop if queue
|
28
|
+
end
|
29
|
+
|
30
|
+
def connect; true; end
|
31
|
+
def close; true; end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#
|
2
|
+
# Run the job inline
|
3
|
+
#
|
4
|
+
module Workling
|
5
|
+
module Clients
|
6
|
+
class NotRemoteClient < Workling::Clients::Base
|
7
|
+
|
8
|
+
def dispatch(clazz, method, options = {})
|
9
|
+
options = Marshal.load(Marshal.dump(options)) # get this to behave more like the remote runners
|
10
|
+
Workling.find(clazz, method).dispatch_to_worker_method(method, options)
|
11
|
+
|
12
|
+
return nil # nada. niente.
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#
|
2
|
+
# Run the job over the spawn plugin. Refer to the README for instructions on
|
3
|
+
# installing Spawn.
|
4
|
+
#
|
5
|
+
# Spawn forks the entire process once for each job. This means that the job starts
|
6
|
+
# with a very low latency, but takes up more memory for each job.
|
7
|
+
#
|
8
|
+
# It's also possible to configure Spawn to start a Thread for each job. Do this
|
9
|
+
# by setting
|
10
|
+
#
|
11
|
+
# Workling::Clients::SpawnClient.options = { :method => :thread }
|
12
|
+
#
|
13
|
+
# Have a look at the Spawn README to find out more about the characteristics of this.
|
14
|
+
#
|
15
|
+
module Workling
|
16
|
+
module Clients
|
17
|
+
class SpawnClient < Workling::Clients::Base
|
18
|
+
|
19
|
+
def self.installed?
|
20
|
+
begin
|
21
|
+
require 'spawn'
|
22
|
+
rescue LoadError
|
23
|
+
end
|
24
|
+
|
25
|
+
Object.const_defined? "Spawn"
|
26
|
+
end
|
27
|
+
|
28
|
+
cattr_writer :options
|
29
|
+
def options
|
30
|
+
return @@options if defined?(@@options)
|
31
|
+
# use thread for development and test modes. easier to hunt down exceptions that way.
|
32
|
+
@@options = { :method => (RAILS_ENV == "test" || RAILS_ENV == "development" ? :fork : :thread) }
|
33
|
+
end
|
34
|
+
|
35
|
+
include Spawn if installed?
|
36
|
+
|
37
|
+
def dispatch(clazz, method, options = {})
|
38
|
+
spawn(SpawnRunner.options) do # exceptions are trapped in here.
|
39
|
+
Workling.find(clazz, method).dispatch_to_worker_method(method, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
return nil # that means nothing!
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'workling/clients/base'
|
2
1
|
require 'json'
|
3
2
|
require 'right_aws'
|
4
3
|
|
@@ -27,15 +26,17 @@ require 'right_aws'
|
|
27
26
|
#
|
28
27
|
module Workling
|
29
28
|
module Clients
|
30
|
-
class SqsClient < Workling::Clients::
|
29
|
+
class SqsClient < Workling::Clients::BrokerBase
|
31
30
|
|
32
|
-
AWS_MAX_QUEUE_NAME
|
31
|
+
unless defined?(AWS_MAX_QUEUE_NAME)
|
32
|
+
AWS_MAX_QUEUE_NAME = 80
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
# Note that 10 is the maximum number of messages that can be retrieved
|
35
|
+
# in a single request.
|
36
|
+
DEFAULT_MESSAGES_PER_REQ = 10
|
37
|
+
DEFAULT_VISIBILITY_TIMEOUT = 30
|
38
|
+
DEFAULT_VISIBILITY_RESERVE = 10
|
39
|
+
end
|
39
40
|
|
40
41
|
# Mainly exposed for testing purposes
|
41
42
|
attr_reader :sqs_options
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#
|
2
|
+
# Spawns a Thread. Used for Tests only, to simulate a remote runner more realistically.
|
3
|
+
#
|
4
|
+
module Workling
|
5
|
+
module Clients
|
6
|
+
class ThreadClient < Workling::Clients::Base
|
7
|
+
|
8
|
+
def dispatch(clazz, method, options = {})
|
9
|
+
Thread.new {
|
10
|
+
Workling.find(clazz, method).dispatch_to_worker_method(method, options)
|
11
|
+
}
|
12
|
+
|
13
|
+
return nil
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'workling/clients/base'
|
2
|
-
Workling.try_load_xmpp4r
|
3
|
-
|
4
1
|
#
|
5
2
|
# An XMPP client
|
6
3
|
#
|
@@ -43,7 +40,20 @@ Workling.try_load_xmpp4r
|
|
43
40
|
|
44
41
|
module Workling
|
45
42
|
module Clients
|
46
|
-
class XmppClient < Workling::Clients::
|
43
|
+
class XmppClient < Workling::Clients::BrokerBase
|
44
|
+
|
45
|
+
def self.load
|
46
|
+
begin
|
47
|
+
gem "xmpp4r"
|
48
|
+
require 'xmpp4r'
|
49
|
+
require "xmpp4r/pubsub"
|
50
|
+
require "xmpp4r/pubsub/helper/servicehelper.rb"
|
51
|
+
require "xmpp4r/pubsub/helper/nodebrowser.rb"
|
52
|
+
require "xmpp4r/pubsub/helper/nodehelper.rb"
|
53
|
+
rescue Exception => e
|
54
|
+
raise WorklingError.new("Couldnt load the XMPP library. check that you have the xmpp4r gem installed")
|
55
|
+
end
|
56
|
+
end
|
47
57
|
|
48
58
|
# starts the client.
|
49
59
|
def connect
|
data/lib/workling/discovery.rb
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
|
3
|
+
#
|
4
|
+
# TODO - Subscribes a single worker to a single queue
|
5
|
+
#
|
6
|
+
module Workling
|
7
|
+
module Invokers
|
8
|
+
class AmqpSingleSubscriber < Workling::Invokers::Base
|
9
|
+
|
10
|
+
def initialize(routing, client_class)
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# Starts EM loop and sets up subscription callback for the worker
|
16
|
+
# Create the queue and bind to exchange using the routing key
|
17
|
+
#
|
18
|
+
def listen
|
19
|
+
EM.run do
|
20
|
+
connect do
|
21
|
+
queue_name = @routing.queue_for
|
22
|
+
routing_key = @routing.routing_key_for
|
23
|
+
|
24
|
+
# temp stuff to hook the queues and exchanges up
|
25
|
+
# wildcard routing - # (match all)
|
26
|
+
exch = MQ.topic
|
27
|
+
q = MQ.queue(queue_name)
|
28
|
+
q.bind(exch, :key => routing_key)
|
29
|
+
|
30
|
+
@client.subscribe(queue_name) do |args|
|
31
|
+
run(queue_name, args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def stop
|
38
|
+
EM.stop if EM.reactor_running?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|