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
data/bin/workling_client
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'rubygems'
|
3
3
|
require 'daemons'
|
4
|
-
require '
|
4
|
+
require File.join(File.dirname(__FILE__), '../lib/workling_daemon')
|
5
5
|
|
6
6
|
daemon_options = {
|
7
7
|
:app_name => "workling",
|
@@ -11,18 +11,20 @@ daemon_options = {
|
|
11
11
|
:multiple => false,
|
12
12
|
:backtrace => true,
|
13
13
|
:monitor => false
|
14
|
-
}.merge(
|
14
|
+
}.merge(WorklingDaemon.parse_daemon_options(ARGV))
|
15
15
|
|
16
16
|
workling_options = {
|
17
17
|
:client_class => "Workling::Clients::MemcacheQueueClient",
|
18
18
|
:invoker_class => "Workling::Remote::Invokers::ThreadedPoller",
|
19
19
|
:routing_class => "Workling::Routing::ClassAndMethodRouting",
|
20
20
|
:rails_root => Dir.pwd,
|
21
|
-
:load_path => [
|
22
|
-
:
|
23
|
-
|
21
|
+
:load_path => ['app/workers/**/*.rb'],
|
22
|
+
:config_path => "config/workling.yml",
|
23
|
+
:rails_env => (ENV['RAILS_ENV'] || "development").dup,
|
24
|
+
:no_rails => false
|
25
|
+
}.merge(WorklingDaemon.parse_workling_options(ARGV))
|
24
26
|
|
25
27
|
Daemons.run_proc(daemon_options[:app_name], daemon_options) do
|
26
28
|
Dir.chdir(workling_options[:rails_root])
|
27
|
-
|
28
|
-
end
|
29
|
+
WorklingDaemon.run(workling_options)
|
30
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/workling.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
#
|
2
2
|
# I can haz am in your Workling are belong to us!
|
3
3
|
#
|
4
|
-
|
5
|
-
require
|
4
|
+
def require_in_tree(name)
|
5
|
+
require File.join(File.dirname(__FILE__), name)
|
6
|
+
end
|
7
|
+
|
8
|
+
require_in_tree 'extensions/mattr_accessor' unless Module.respond_to?(:mattr_accessor)
|
9
|
+
require_in_tree 'extensions/cattr_accessor' unless Class.respond_to?(:cattr_accessor)
|
6
10
|
|
7
11
|
gem 'activesupport'
|
8
12
|
require 'active_support/inflector'
|
@@ -51,30 +55,72 @@ module Workling
|
|
51
55
|
mattr_accessor :load_path
|
52
56
|
@@load_path = [ File.expand_path(path('app', 'workers')) ]
|
53
57
|
|
54
|
-
VERSION = "0.4.9"
|
58
|
+
VERSION = "0.4.9" unless defined?(VERSION)
|
55
59
|
|
56
60
|
#
|
57
|
-
# determine the
|
61
|
+
# determine the client to use if nothing is specifically set. workling will try to detect
|
58
62
|
# starling, spawn, or bj, in that order. if none of these are found, notremoterunner will
|
59
63
|
# be used.
|
60
64
|
#
|
61
|
-
|
62
|
-
# Workling::Remote.dispatcher = Workling::Remote::Runners::StarlingRunner.new
|
63
|
-
#
|
64
|
-
def self.default_runner
|
65
|
+
def self.select_and_build_default_client
|
65
66
|
if env == "test"
|
66
|
-
Workling::
|
67
|
-
elsif
|
68
|
-
Workling::
|
69
|
-
elsif
|
70
|
-
Workling::
|
71
|
-
elsif bj_installed?
|
72
|
-
Workling::Remote::Runners::BackgroundjobRunner.new
|
67
|
+
Workling::Clients::NotRemoteClient.new
|
68
|
+
elsif Workling::Clients::SpawnClient.installed?
|
69
|
+
Workling::Clients::SpawnClient.new
|
70
|
+
elsif Workling::Clients::BackgroundjobClient.installed?
|
71
|
+
Workling::Clients::BackgroundjobClient.new
|
73
72
|
else
|
74
|
-
Workling::
|
73
|
+
Workling::Clients::NotRemoteClient.new
|
75
74
|
end
|
76
75
|
end
|
77
|
-
|
76
|
+
|
77
|
+
#
|
78
|
+
# this will build the client to use for job dispatching and retrieval
|
79
|
+
# The look up does the following:
|
80
|
+
# 1. if Workling::Remote.client is set explicitly then that client is used
|
81
|
+
# 2. if workling.yml (or whatever file is used) contains a client section then that is used
|
82
|
+
# 3. otherwise the default client is built using the Workling.select_and_build_default_client method
|
83
|
+
#
|
84
|
+
def self.select_and_build_client
|
85
|
+
case(Workling.config[:client])
|
86
|
+
when 'amqp'
|
87
|
+
Workling::Clients::AmqpClient
|
88
|
+
|
89
|
+
when 'amqp_exchange'
|
90
|
+
Workling::Clients::AmqpExchangeClient
|
91
|
+
|
92
|
+
when 'memcache', 'starling'
|
93
|
+
Workling::Clients::MemcacheQueueClient
|
94
|
+
|
95
|
+
when 'memory_queue' # this one is pretty useles...
|
96
|
+
Workling::Clients::MemoryQueueClient
|
97
|
+
|
98
|
+
when 'sqs'
|
99
|
+
Workling::Clients::SqsClient
|
100
|
+
|
101
|
+
when 'xmpp'
|
102
|
+
Workling::Clients::XmppClient
|
103
|
+
|
104
|
+
when 'backgroundjob'
|
105
|
+
Workling::Clients::BackgroundjobClient
|
106
|
+
|
107
|
+
when 'not_remote'
|
108
|
+
Workling::Clients::NotRemoteClient
|
109
|
+
|
110
|
+
when 'not'
|
111
|
+
Workling::Clients::NotClient
|
112
|
+
|
113
|
+
when 'spawn'
|
114
|
+
Workling::Clients::SpawnClient
|
115
|
+
|
116
|
+
when 'thread'
|
117
|
+
Workling::Clients::ThreadClient
|
118
|
+
|
119
|
+
else
|
120
|
+
select_and_build_default_client
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
78
124
|
#
|
79
125
|
# gets the worker instance, given a class. the optional method argument will cause an
|
80
126
|
# exception to be raised if the worker instance does not respoind to said method.
|
@@ -88,108 +134,66 @@ module Workling
|
|
88
134
|
raise_not_found(clazz, method) if method && !inst.respond_to?(method)
|
89
135
|
inst
|
90
136
|
end
|
91
|
-
|
137
|
+
|
92
138
|
# returns Workling::Return::Store.instance.
|
93
139
|
def self.return
|
94
140
|
Workling::Return::Store.instance
|
95
141
|
end
|
96
142
|
|
97
|
-
# is spawn installed?
|
98
|
-
def self.spawn_installed?
|
99
|
-
begin
|
100
|
-
require 'spawn'
|
101
|
-
rescue LoadError
|
102
|
-
end
|
103
|
-
|
104
|
-
Object.const_defined? "Spawn"
|
105
|
-
end
|
106
|
-
|
107
|
-
# is starling installed?
|
108
|
-
def self.starling_installed?
|
109
|
-
begin
|
110
|
-
require 'starling'
|
111
|
-
rescue LoadError
|
112
|
-
end
|
113
|
-
|
114
|
-
Object.const_defined? "Starling"
|
115
|
-
end
|
116
|
-
|
117
|
-
# is bj installed?
|
118
|
-
def self.bj_installed?
|
119
|
-
Object.const_defined? "Bj"
|
120
|
-
end
|
121
|
-
|
122
|
-
# Attempts to load the memcache-client gem
|
123
|
-
def self.try_load_a_memcache_client
|
124
|
-
begin
|
125
|
-
gem 'memcache-client'
|
126
|
-
require 'memcache'
|
127
|
-
rescue Gem::LoadError
|
128
|
-
Workling::Base.logger.info "WORKLING: couldn't find memcache-client. Install: \"gem install memcache-client\". "
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
# attempts to load amqp and writes out descriptive error message if not present
|
133
|
-
def self.try_load_an_amqp_client
|
134
|
-
begin
|
135
|
-
require 'mq'
|
136
|
-
rescue Exception => e
|
137
|
-
raise WorklingError.new(
|
138
|
-
"WORKLING: couldn't find the ruby amqp client - you need it for the amqp runner. " \
|
139
|
-
"Install from github: gem sources -a http://gems.github.com/ && sudo gem install tmm1-amqp "
|
140
|
-
)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# attempts to load xmpp4r library and writes out descriptive error message if not present
|
145
|
-
def self.try_load_xmpp4r
|
146
|
-
begin
|
147
|
-
gem "xmpp4r"
|
148
|
-
require 'xmpp4r'
|
149
|
-
require "xmpp4r/pubsub"
|
150
|
-
require "xmpp4r/pubsub/helper/servicehelper.rb"
|
151
|
-
require "xmpp4r/pubsub/helper/nodebrowser.rb"
|
152
|
-
require "xmpp4r/pubsub/helper/nodehelper.rb"
|
153
|
-
rescue Exception => e
|
154
|
-
raise WorklingError.new("Couldnt load the XMPP library. check that you have the xmpp4r gem installed")
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
|
159
143
|
#
|
160
144
|
# returns a config hash. reads ./config/workling.yml
|
161
145
|
#
|
146
|
+
mattr_writer :config
|
162
147
|
def self.config
|
163
148
|
return @@config if defined?(@@config) && @@config
|
164
149
|
|
165
|
-
config_path = File.join(RAILS_ROOT, 'config', 'workling.yml')
|
166
150
|
return nil unless File.exists?(config_path)
|
167
|
-
|
168
|
-
@@config ||= YAML.load_file(config_path)[
|
151
|
+
|
152
|
+
@@config ||= YAML.load_file(config_path)[env || 'development'].symbolize_keys
|
169
153
|
@@config[:memcache_options].symbolize_keys! if @@config[:memcache_options]
|
170
154
|
@@config
|
171
155
|
end
|
172
|
-
|
156
|
+
|
157
|
+
mattr_writer :config_path
|
158
|
+
def self.config_path
|
159
|
+
return @@config_path if defined?(@@config_path) && @@config_path
|
160
|
+
@@config_path = File.join(RAILS_ROOT, 'config', 'workling.yml')
|
161
|
+
end
|
162
|
+
|
173
163
|
#
|
174
164
|
# Raises exceptions thrown inside of the worker. normally, these are logged to
|
175
165
|
# logger.error. it's easy to miss these log calls while developing, though.
|
176
166
|
#
|
177
|
-
|
178
|
-
|
179
|
-
|
167
|
+
mattr_writer :raise_exceptions
|
168
|
+
def raise_exceptions
|
169
|
+
return @@raise_exceptions if defined?(@@raise_exceptions)
|
170
|
+
@@raise_exceptions = (RAILS_ENV == "test" || RAILS_ENV == "development")
|
171
|
+
end
|
172
|
+
|
180
173
|
def self.raise_exceptions?
|
181
174
|
@@raise_exceptions
|
182
175
|
end
|
183
|
-
|
176
|
+
|
184
177
|
private
|
185
178
|
def self.raise_not_found(clazz, method)
|
186
179
|
raise Workling::WorklingNotFoundError.new("could not find #{ clazz }:#{ method } workling. ")
|
187
180
|
end
|
181
|
+
|
188
182
|
end
|
189
183
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
184
|
+
require_in_tree "workling/discovery"
|
185
|
+
require_in_tree "workling/base"
|
186
|
+
require_in_tree "workling/remote"
|
187
|
+
|
188
|
+
require_in_tree "workling/clients/base"
|
189
|
+
require_in_tree "workling/clients/broker_base"
|
190
|
+
require_in_tree "workling/invokers/base"
|
191
|
+
require_in_tree "workling/return/store/base"
|
192
|
+
require_in_tree "workling/routing/base"
|
193
|
+
|
194
|
+
# load all possible extension classes
|
195
|
+
["clients", "invokers", "return/store", "routing"].each do |e_dirs|
|
196
|
+
Dir.glob(File.join(File.dirname(__FILE__), "workling", e_dirs, "*.rb")).each do |rb_file|
|
197
|
+
require File.join(File.dirname(rb_file), File.basename(rb_file, ".rb"))
|
198
|
+
end
|
199
|
+
end
|
data/lib/workling/base.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
#require 'struct'
|
2
|
-
|
3
1
|
#
|
4
2
|
# All worker classes must inherit from this class, and be saved in app/workers.
|
5
3
|
#
|
@@ -16,9 +14,14 @@
|
|
16
14
|
#
|
17
15
|
module Workling
|
18
16
|
class Base
|
17
|
+
|
19
18
|
cattr_writer :logger
|
20
19
|
def self.logger
|
21
|
-
@@logger ||= ::RAILS_DEFAULT_LOGGER
|
20
|
+
@@logger ||= defined?(RAILS_DEFAULT_LOGGER) ? ::RAILS_DEFAULT_LOGGER : Logger.new($stdout)
|
21
|
+
end
|
22
|
+
|
23
|
+
def logger
|
24
|
+
self.class.logger
|
22
25
|
end
|
23
26
|
|
24
27
|
cattr_accessor :exposed_methods
|
@@ -83,7 +86,6 @@ module Workling
|
|
83
86
|
raise e
|
84
87
|
rescue Exception => e
|
85
88
|
notify_exception e, method, options
|
86
|
-
on_error(e) if respond_to?(:on_error)
|
87
89
|
|
88
90
|
# reraise after logging. the exception really can't go anywhere in many cases. (spawn traps the exception)
|
89
91
|
raise e if Workling.raise_exceptions?
|
@@ -103,13 +105,6 @@ module Workling
|
|
103
105
|
super
|
104
106
|
end
|
105
107
|
end
|
106
|
-
|
107
|
-
def self.logger
|
108
|
-
@logger ||= defined?(RAILS_DEFAULT_LOGGER) ? ::RAILS_DEFAULT_LOGGER : Logger.new($stdout)
|
109
|
-
end
|
110
108
|
|
111
|
-
def logger
|
112
|
-
self.class.logger
|
113
|
-
end
|
114
109
|
end
|
115
110
|
end
|
@@ -1,13 +1,21 @@
|
|
1
|
-
require 'workling/clients/base'
|
2
|
-
Workling.try_load_an_amqp_client
|
3
|
-
|
4
1
|
#
|
5
2
|
# An Ampq client
|
6
3
|
#
|
7
4
|
module Workling
|
8
5
|
module Clients
|
9
|
-
class AmqpClient < Workling::Clients::
|
10
|
-
|
6
|
+
class AmqpClient < Workling::Clients::BrokerBase
|
7
|
+
|
8
|
+
def self.load
|
9
|
+
begin
|
10
|
+
require 'mq'
|
11
|
+
rescue Exception => e
|
12
|
+
raise WorklingError.new(
|
13
|
+
"WORKLING: couldn't find the ruby amqp client - you need it for the amqp runner. " \
|
14
|
+
"Install from github: gem sources -a http://gems.github.com/ && sudo gem install tmm1-amqp "
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
11
19
|
# starts the client.
|
12
20
|
def connect
|
13
21
|
begin
|
@@ -1,13 +1,21 @@
|
|
1
|
-
require 'workling/clients/base'
|
2
|
-
Workling.try_load_an_amqp_client
|
3
|
-
|
4
1
|
#
|
5
2
|
# An Ampq client
|
6
3
|
#
|
7
4
|
module Workling
|
8
5
|
module Clients
|
9
|
-
class AmqpExchangeClient < Workling::Clients::
|
10
|
-
|
6
|
+
class AmqpExchangeClient < Workling::Clients::BrokerBase
|
7
|
+
|
8
|
+
def self.load
|
9
|
+
begin
|
10
|
+
require 'mq'
|
11
|
+
rescue Exception => e
|
12
|
+
raise WorklingError.new(
|
13
|
+
"WORKLING: couldn't find the ruby amqp client - you need it for the amqp runner. " \
|
14
|
+
"Install from github: gem sources -a http://gems.github.com/ && sudo gem install tmm1-amqp "
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
11
19
|
# starts the client.
|
12
20
|
def connect
|
13
21
|
begin
|
@@ -16,22 +24,19 @@ module Workling
|
|
16
24
|
raise WorklingError.new("couldn't start amq client. if you're running this in a server environment, then make sure the server is evented (ie use thin or evented mongrel, not normal mongrel.)")
|
17
25
|
end
|
18
26
|
end
|
19
|
-
|
27
|
+
|
20
28
|
# no need for explicit closing. when the event loop
|
21
29
|
# terminates, the connection is closed anyway.
|
22
30
|
def close; true; end
|
23
|
-
|
31
|
+
|
24
32
|
# subscribe to a queue
|
25
33
|
def subscribe(key)
|
26
34
|
@amq.queue(key).subscribe do |header, body|
|
27
|
-
|
28
|
-
puts "***** received msg with header - #{header.inspect}"
|
29
|
-
|
30
35
|
value = YAML.load(body)
|
31
36
|
yield value
|
32
37
|
end
|
33
38
|
end
|
34
|
-
|
39
|
+
|
35
40
|
# request and retrieve work
|
36
41
|
def retrieve(key)
|
37
42
|
@amq.queue(key)
|
@@ -40,11 +45,14 @@ module Workling
|
|
40
45
|
# publish message to exchange
|
41
46
|
# using the specified routing key
|
42
47
|
def request(exchange_name, value)
|
48
|
+
exchange_name = "amq.topic"
|
49
|
+
|
43
50
|
key = value.delete(:routing_key)
|
44
51
|
msg = YAML.dump(value)
|
45
52
|
exchange = @amq.topic(exchange_name)
|
46
53
|
exchange.publish(msg, :routing_key => key)
|
47
54
|
end
|
55
|
+
|
48
56
|
end
|
49
57
|
end
|
50
58
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Workling
|
2
|
+
module Clients
|
3
|
+
class BackgroundjobClient < Workling::Clients::Base
|
4
|
+
|
5
|
+
def self.installed?
|
6
|
+
Object.const_defined? "Bj"
|
7
|
+
end
|
8
|
+
|
9
|
+
# passes the job to bj by serializing the options to xml and passing them to
|
10
|
+
# ./script/bj_invoker.rb, which in turn routes the deserialized args to the
|
11
|
+
# appropriate worker.
|
12
|
+
def dispatch(clazz, method, options = {})
|
13
|
+
stdin = Workling::Remote.routing.queue_for(clazz, method) +
|
14
|
+
" " +
|
15
|
+
options.to_xml(:indent => 0, :skip_instruct => true)
|
16
|
+
|
17
|
+
Bj.submit "./script/runner ./script/bj_invoker.rb",
|
18
|
+
:stdin => stdin
|
19
|
+
|
20
|
+
return nil # that means nothing!
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|