derfred-workling 0.4.9.1 → 0.4.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/lib/cattr_accessor.rb +51 -0
  2. data/lib/mattr_accessor.rb +55 -0
  3. data/lib/rude_q/client.rb +11 -0
  4. data/lib/workling/base.rb +115 -0
  5. data/lib/workling/clients/amqp_client.rb +38 -0
  6. data/lib/workling/clients/amqp_exchange_client.rb +50 -0
  7. data/lib/workling/clients/base.rb +57 -0
  8. data/lib/workling/clients/memcache_queue_client.rb +91 -0
  9. data/lib/workling/clients/sqs_client.rb +162 -0
  10. data/lib/workling/clients/xmpp_client.rb +100 -0
  11. data/lib/workling/discovery.rb +16 -0
  12. data/lib/workling/remote/invokers/amqp_single_subscriber.rb +45 -0
  13. data/lib/workling/remote/invokers/base.rb +124 -0
  14. data/lib/workling/remote/invokers/basic_poller.rb +41 -0
  15. data/lib/workling/remote/invokers/eventmachine_subscriber.rb +41 -0
  16. data/lib/workling/remote/invokers/looped_subscriber.rb +38 -0
  17. data/lib/workling/remote/invokers/thread_pool_poller.rb +169 -0
  18. data/lib/workling/remote/invokers/threaded_poller.rb +153 -0
  19. data/lib/workling/remote/runners/amqp_exchange_runner.rb +45 -0
  20. data/lib/workling/remote/runners/backgroundjob_runner.rb +35 -0
  21. data/lib/workling/remote/runners/base.rb +42 -0
  22. data/lib/workling/remote/runners/client_runner.rb +46 -0
  23. data/lib/workling/remote/runners/not_remote_runner.rb +23 -0
  24. data/lib/workling/remote/runners/not_runner.rb +17 -0
  25. data/lib/workling/remote/runners/rudeq_runner.rb +23 -0
  26. data/lib/workling/remote/runners/spawn_runner.rb +38 -0
  27. data/lib/workling/remote/runners/starling_runner.rb +13 -0
  28. data/lib/workling/remote.rb +69 -0
  29. data/lib/workling/return/store/base.rb +42 -0
  30. data/lib/workling/return/store/iterator.rb +24 -0
  31. data/lib/workling/return/store/memory_return_store.rb +26 -0
  32. data/lib/workling/return/store/rudeq_return_store.rb +24 -0
  33. data/lib/workling/return/store/starling_return_store.rb +31 -0
  34. data/lib/workling/routing/base.rb +16 -0
  35. data/lib/workling/routing/class_and_method_routing.rb +57 -0
  36. data/lib/workling/routing/static_routing.rb +47 -0
  37. data/lib/workling/rudeq/client.rb +17 -0
  38. data/lib/workling/rudeq/poller.rb +116 -0
  39. data/lib/workling/rudeq.rb +7 -0
  40. data/lib/workling.rb +195 -0
  41. data/lib/workling_server.rb +108 -0
  42. data/script/bj_invoker.rb +11 -0
  43. data/script/starling_status.rb +37 -0
  44. metadata +44 -1
@@ -0,0 +1,57 @@
1
+ require 'workling/routing/base'
2
+
3
+ #
4
+ # Holds a hash of routes. Each Worker method has a corresponding hash entry after building.
5
+ #
6
+ module Workling
7
+ module Routing
8
+ class ClassAndMethodRouting < Base
9
+
10
+ # initializes and builds routing hash.
11
+ def initialize(*args)
12
+ super
13
+
14
+ build
15
+ end
16
+
17
+ # returns the worker method name, given the routing string.
18
+ def method_name(queue)
19
+ self[queue].method_for(queue)
20
+ end
21
+
22
+ # returns the routing string, given a class and method. delegating.
23
+ def queue_for(clazz, method)
24
+ ClassAndMethodRouting.queue_for(clazz, method)
25
+ end
26
+
27
+ # returns the routing string, given a class and method.
28
+ def self.queue_for(clazz, method)
29
+ # this is lifted from the Rails constantize method
30
+ clazz = Object.module_eval("::#{clazz}") unless clazz.is_a?(Class)
31
+ clazz.queue_for method
32
+ end
33
+
34
+ # returns all routed
35
+ def queue_names
36
+ self.keys
37
+ end
38
+
39
+ # dare you to remove this! go on!
40
+ def queue_names_routing_class(clazz)
41
+ self.select { |x, y| y.is_a?(clazz) }.map { |x, y| x }
42
+ end
43
+
44
+ private
45
+ def build
46
+ Workling::Discovery.discovered.each do |clazz|
47
+ methods = clazz.public_instance_methods(false)
48
+ methods.each do |method|
49
+ next if method == 'create' # Skip the create method
50
+ queue = queue_for(clazz, method)
51
+ self[queue] = clazz.new
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,47 @@
1
+ require 'workling/routing/base'
2
+
3
+ #
4
+ # Holds a single route for a dedicated worker (if you want more worker processes, run more workers)
5
+ #
6
+ module Workling
7
+ module Routing
8
+ class StaticRouting < Base
9
+
10
+ #
11
+ # ./script/workling_client run -- <worker_class> <worker_method> <routing_key>
12
+ # ./script/workling_client run -- <worker_class> <worker_method> <routing_key> <queue_name>
13
+ #
14
+ def initialize(*args)
15
+ @worker = args[0].constantize.new
16
+ @method_name = args[1]
17
+ @routing_key = args[2]
18
+
19
+ if(args.size==4)
20
+ @queue_name = args[3]
21
+ else
22
+ @queue_name = [@worker.class.to_s.tableize, @method_name, @routing_key].join("__")
23
+ end
24
+
25
+ # so routing[x] hash access works as expected
26
+ self.default = @worker
27
+
28
+ puts "** static routing: queue - #{@queue_name}, routing_key - #{@routing_key}, method - #{@method_name}, worker - #{@worker.class}"
29
+ end
30
+
31
+ # returns the worker method name, given the routing string.
32
+ def method_name(queue=nil); @method_name; end
33
+
34
+ def routing_key_for; @routing_key; end
35
+
36
+ # returns the routing string, given a class and method. delegating.
37
+ # TODO - we can check for consistency here with clazz and methods vs. current configuration of this single route
38
+ def queue_for(clazz=nil, method=nil); @queue_name; end
39
+
40
+ # returns array containing the single configured route
41
+ def queue_names; [@queue_name]; end
42
+
43
+ # TODO - not sure what this is...
44
+ def queue_names_routing_class(clazz); @worker.class; end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ require 'workling/rudeq'
2
+
3
+ module Workling
4
+ module Rudeq
5
+ class Client
6
+ attr_reader :queue
7
+
8
+ def initialize
9
+ @queue = Workling::Rudeq.config[:queue_class].constantize
10
+ end
11
+
12
+ def method_missing(method, *args)
13
+ @queue.send(method, *args)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,116 @@
1
+ require 'workling/rudeq'
2
+
3
+ module Workling
4
+ module Rudeq
5
+
6
+ class Poller
7
+
8
+ cattr_accessor :sleep_time # Seconds to sleep before looping
9
+ cattr_accessor :reset_time # Seconds to wait while resetting connection
10
+
11
+ def initialize(routing)
12
+ Poller.sleep_time = Workling::Rudeq.config[:sleep_time] || 2
13
+ Poller.reset_time = Workling::Rudeq.config[:reset_time] || 30
14
+
15
+ @routing = routing
16
+ @workers = ThreadGroup.new
17
+ end
18
+
19
+ def logger
20
+ Workling::Base.logger
21
+ end
22
+
23
+ def listen
24
+
25
+ # Allow concurrency for our tasks
26
+ ActiveRecord::Base.allow_concurrency = true
27
+
28
+ # Create a thread for each worker.
29
+ Workling::Discovery.discovered.each do |clazz|
30
+ logger.debug("Discovered listener #{clazz}")
31
+ @workers.add(Thread.new(clazz) { |c| clazz_listen(c) })
32
+ end
33
+
34
+ # Wait for all workers to complete
35
+ @workers.list.each { |t| t.join }
36
+
37
+ # Clean up all the connections.
38
+ ActiveRecord::Base.verify_active_connections!
39
+ end
40
+
41
+ # gracefully stop processing
42
+ def stop
43
+ @workers.list.each { |w| w[:shutdown] = true }
44
+ end
45
+
46
+ ##
47
+ ## Thread procs
48
+ ##
49
+
50
+ # Listen for one worker class
51
+ def clazz_listen(clazz)
52
+
53
+ logger.debug("Listener thread #{clazz.name} started")
54
+
55
+ # Read thread configuration if available
56
+ if Rudeq.config.has_key?(:listeners)
57
+ if Rudeq.config[:listeners].has_key?(clazz.to_s)
58
+ config = Rudeq.config[:listeners][clazz.to_s].symbolize_keys
59
+ thread_sleep_time = config[:sleep_time] if config.has_key?(:sleep_time)
60
+ end
61
+ end
62
+
63
+ hread_sleep_time ||= self.class.sleep_time
64
+
65
+ connection = Workling::Rudeq::Client.new
66
+ puts "** Starting Workling::Rudeq::Client for #{clazz.name} queue"
67
+
68
+ # Start dispatching those messages
69
+ while (!Thread.current[:shutdown]) do
70
+ begin
71
+
72
+ # Keep MySQL connection alive
73
+ unless ActiveRecord::Base.connection.active?
74
+ unless ActiveRecord::Base.connection.reconnect!
75
+ logger.fatal("FAILED - Database not available")
76
+ break
77
+ end
78
+ end
79
+
80
+ # Dispatch and process the messages
81
+ n = dispatch!(connection, clazz)
82
+ logger.debug("Listener thread #{clazz.name} processed #{n.to_s} queue items") if n > 0
83
+ sleep(self.class.sleep_time) unless n > 0
84
+ end
85
+ end
86
+
87
+ logger.debug("Listener thread #{clazz.name} ended")
88
+ end
89
+
90
+ # Dispatcher for one worker class.
91
+ # Returns the number of worker methods called
92
+ def dispatch!(connection, clazz)
93
+ n = 0
94
+ for queue in @routing.queue_names_routing_class(clazz)
95
+ begin
96
+ result = connection.get(queue)
97
+ if result
98
+ n += 1
99
+ handler = @routing[queue]
100
+ method_name = @routing.method_name(queue)
101
+ logger.debug("Calling #{handler.class.to_s}\##{method_name}(#{result.inspect})")
102
+ handler.send(method_name, result)
103
+ end
104
+ rescue
105
+ logger.error("FAILED to connect with queue #{ queue }: #{ e } }")
106
+ raise e
107
+ rescue Object => e
108
+ logger.error("FAILED to process queue #{ queue }. #{ @routing[queue] } could not handle invocation of #{ @routing.method_name(queue) } with #{ result.inspect }: #{ e }.\n#{ e.backtrace.join("\n") }")
109
+ end
110
+ end
111
+
112
+ return n
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,7 @@
1
+ module Workling
2
+ module Rudeq
3
+ def self.config
4
+ @@config ||= {:queue_class => "RudeQueue"}
5
+ end
6
+ end
7
+ end
data/lib/workling.rb ADDED
@@ -0,0 +1,195 @@
1
+ #
2
+ # I can haz am in your Workling are belong to us!
3
+ #
4
+ require 'mattr_accessor' unless Module.respond_to?(:mattr_accessor)
5
+ require 'cattr_accessor' unless Class.respond_to?(:cattr_accessor)
6
+
7
+ gem 'activesupport'
8
+ require 'active_support/inflector'
9
+ require 'active_support/core_ext/hash/keys'
10
+
11
+ class Hash #:nodoc:
12
+ include ActiveSupport::CoreExtensions::Hash::Keys
13
+ end
14
+
15
+ require 'yaml'
16
+
17
+ module Workling
18
+ class WorklingError < StandardError; end
19
+ class WorklingNotFoundError < WorklingError; end
20
+ class WorklingConnectionError < WorklingError; end
21
+ class QueueserverNotFoundError < WorklingError
22
+ def initialize
23
+ super "config/workling.yml configured to connect to queue server on #{ Workling.config[:listens_on] } for this environment. could not connect to queue server on this host:port. for starling users: pass starling the port with -p flag when starting it. If you don't want to use Starling, then explicitly set Workling::Remote.dispatcher (see README for an example)"
24
+ end
25
+ end
26
+
27
+ class ConfigurationError < WorklingError
28
+ def initialize
29
+ super File.exist?(Workling.path('config', 'starling.yml')) ?
30
+ "config/starling.yml has been depracated. rename your config file to config/workling.yml then try again!" :
31
+ "config/workling.yml could not be loaded. check out README.markdown to see what this file should contain. "
32
+ end
33
+ end
34
+
35
+ def self.path(*args)
36
+ if defined?(RAILS_ROOT)
37
+ File.join(RAILS_ROOT, *args)
38
+ else
39
+ File.join(Dir.pwd, *args)
40
+ end
41
+ end
42
+
43
+ def self.env
44
+ @env ||= if defined?(RAILS_ENV)
45
+ RAILS_ENV.to_s
46
+ elsif defined?(RACK_ENV)
47
+ RACK_ENV.to_s
48
+ end
49
+ end
50
+
51
+ mattr_accessor :load_path
52
+ @@load_path = [ File.expand_path(path('app', 'workers')) ]
53
+
54
+ VERSION = "0.4.9"
55
+
56
+ #
57
+ # determine the runner to use if nothing is specifically set. workling will try to detect
58
+ # starling, spawn, or bj, in that order. if none of these are found, notremoterunner will
59
+ # be used.
60
+ #
61
+ # this can be overridden by setting Workling::Remote.dispatcher, eg:
62
+ # Workling::Remote.dispatcher = Workling::Remote::Runners::StarlingRunner.new
63
+ #
64
+ def self.default_runner
65
+ if env == "test"
66
+ Workling::Remote::Runners::NotRemoteRunner.new
67
+ elsif starling_installed?
68
+ Workling::Remote::Runners::StarlingRunner.new
69
+ elsif spawn_installed?
70
+ Workling::Remote::Runners::SpawnRunner.new
71
+ elsif bj_installed?
72
+ Workling::Remote::Runners::BackgroundjobRunner.new
73
+ else
74
+ Workling::Remote::Runners::NotRemoteRunner.new
75
+ end
76
+ end
77
+
78
+ #
79
+ # gets the worker instance, given a class. the optional method argument will cause an
80
+ # exception to be raised if the worker instance does not respoind to said method.
81
+ #
82
+ def self.find(clazz, method = nil)
83
+ begin
84
+ inst = clazz.to_s.camelize.constantize.new
85
+ rescue NameError
86
+ raise_not_found(clazz, method)
87
+ end
88
+ raise_not_found(clazz, method) if method && !inst.respond_to?(method)
89
+ inst
90
+ end
91
+
92
+ # returns Workling::Return::Store.instance.
93
+ def self.return
94
+ Workling::Return::Store.instance
95
+ end
96
+
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
+ #
160
+ # returns a config hash. reads ./config/workling.yml
161
+ #
162
+ def self.config
163
+ return @@config if defined?(@@config) && @@config
164
+
165
+ config_path = File.join(RAILS_ROOT, 'config', 'workling.yml')
166
+ return nil unless File.exists?(config_path)
167
+
168
+ @@config ||= YAML.load_file(config_path)[RAILS_ENV || 'development'].symbolize_keys
169
+ @@config[:memcache_options].symbolize_keys! if @@config[:memcache_options]
170
+ @@config
171
+ end
172
+
173
+ #
174
+ # Raises exceptions thrown inside of the worker. normally, these are logged to
175
+ # logger.error. it's easy to miss these log calls while developing, though.
176
+ #
177
+ mattr_accessor :raise_exceptions
178
+ @@raise_exceptions = (RAILS_ENV == "test" || RAILS_ENV == "development")
179
+
180
+ def self.raise_exceptions?
181
+ @@raise_exceptions
182
+ end
183
+
184
+ private
185
+ def self.raise_not_found(clazz, method)
186
+ raise Workling::WorklingNotFoundError.new("could not find #{ clazz }:#{ method } workling. ")
187
+ end
188
+ end
189
+
190
+ require "workling/discovery"
191
+ require "workling/base"
192
+ require "workling/remote"
193
+ require "workling/return/store/base"
194
+ require "workling/return/store/memory_return_store"
195
+ require "workling/return/store/starling_return_store"
@@ -0,0 +1,108 @@
1
+ require 'optparse'
2
+
3
+ class WorklingServer
4
+ @@in_server_mode = false
5
+ def self.in_server_mode
6
+ @@in_server_mode
7
+ end
8
+
9
+ def self.in_server_mode=(server_mode)
10
+ @@in_server_mode = server_mode
11
+ end
12
+
13
+
14
+ def self.partition_options(args)
15
+ daemon = []
16
+ workling = []
17
+ split_point = args.index("--") || args.size
18
+ daemon = args[0...split_point] if split_point > 0
19
+ workling = args[(split_point+1)..-1] if split_point and split_point < args.size
20
+ [daemon, workling]
21
+ end
22
+
23
+ def self.partition_daemons_options(args)
24
+ standard_options = %W{start stop restart run zap -t --ontop -f --force -h --help --version}
25
+ pass_through = args.select { |a| standard_options.include? a }
26
+ custom_options = args.reject { |a| standard_options.include? a }
27
+
28
+ [pass_through, custom_options]
29
+ end
30
+
31
+ def self.parse_daemon_options(argv)
32
+ options = {}
33
+ pass_through, args = partition_daemons_options argv
34
+ opts = OptionParser.new do |opts|
35
+ opts.banner = 'Usage: myapp [options]'
36
+ opts.separator ''
37
+ opts.on('-a', '--app-name APP_NAME', String,"specify the process name") { |v| options[:app_name] = v }
38
+ opts.on('-d', '--dir DIR', String, "the directory to run in") { |v| options[:dir] = v }
39
+ opts.on('-m', '--monitor',"specify the process name") { |v| options[:monitor] = true }
40
+ opts.on('-t', '--ontop') { |k, v| pass_through << v }
41
+ end
42
+ opts.parse!(partition_options(args).first)
43
+ options.merge(:ARGV => pass_through)
44
+ end
45
+
46
+ def self.parse_workling_options(args)
47
+ options = {}
48
+ opts = OptionParser.new do |opts|
49
+ opts.banner = 'Usage: myapp [options]'
50
+ opts.separator ''
51
+ opts.on('-c', '--client CLIENT', String,"specify the client class") { |v| options[:client_class] = v }
52
+ opts.on('-i', '--invoker INVOKER', String,"specify the invoker class") { |v| options[:invoker_class] = v }
53
+ opts.on('-r', '--routing ROUTING', String,"specify the routing class") { |v| options[:routing_class] = v }
54
+ opts.on('-l', '--load-path LOADPATH', String,"specify the load_path for the workers") { |v| options[:load_path] = v }
55
+ opts.on('-e', '--environment ENVIRONMENT', String,"specify the environment") { |v| options[:rails_env] = v }
56
+ end
57
+ opts.parse!(partition_options(args).last)
58
+ options
59
+ end
60
+
61
+
62
+ def self.build_poller(options)
63
+ require 'workling/remote'
64
+ ["remote/invokers/*.rb", "routing/*.rb"].each do |pattern|
65
+ Dir.glob(pattern).each do |f|
66
+ require File.join(File.dirname(f), File.basename(f, ".rb"))
67
+ end
68
+ end
69
+
70
+ routing_class = Object.module_eval("::#{options[:routing_class]}")
71
+ client_class = Object.module_eval("::#{options[:client_class]}")
72
+ invoker_class = Object.module_eval("::#{options[:invoker_class]}")
73
+ invoker_class.new(routing_class.new, client_class)
74
+ end
75
+
76
+
77
+ def self.run(options)
78
+ WorklingServer.in_server_mode = true
79
+
80
+ ENV["RAILS_ENV"] = options[:rails_env]
81
+ puts "=> Loading Rails with #{ENV["RAILS_ENV"]} environment..."
82
+
83
+ require options[:rails_root] + '/config/environment'
84
+
85
+ Workling.load_path = options[:load_path]
86
+
87
+ Workling::Discovery.discover!
88
+ Workling.config
89
+
90
+ poller = build_poller options
91
+
92
+ puts '** Rails loaded.'
93
+ puts "** Starting #{ poller.class }..."
94
+ puts '** Use CTRL-C to stop.'
95
+
96
+ ActiveRecord::Base.logger = Workling::Base.logger
97
+ ActionController::Base.logger = Workling::Base.logger
98
+
99
+ trap(:INT) { poller.stop; exit }
100
+
101
+ begin
102
+ poller.listen
103
+ ensure
104
+ puts '** No Worklings found.' if Workling::Discovery.discovered.blank?
105
+ puts '** Exiting'
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,11 @@
1
+ @routing = Workling::Routing::ClassAndMethodRouting.new
2
+ unnormalized = REXML::Text::unnormalize(STDIN.read)
3
+ message, command, args = *unnormalized.match(/(^[^ ]*) (.*)/)
4
+ options = Hash.from_xml(args)["hash"]
5
+
6
+ if workling = @routing[command]
7
+ options = options.symbolize_keys
8
+ method_name = @routing.method_name(command)
9
+
10
+ workling.dispatch_to_worker_method(method_name, options)
11
+ end
@@ -0,0 +1,37 @@
1
+ require 'pp'
2
+
3
+ puts '=> Loading Rails...'
4
+
5
+ require File.dirname(__FILE__) + '/../config/environment'
6
+ require File.dirname(__FILE__) + '/../vendor/plugins/workling/lib/workling/remote/invokers/basic_poller'
7
+ require File.dirname(__FILE__) + '/../vendor/plugins/workling/lib/workling/routing/class_and_method_routing'
8
+
9
+ puts '** Rails loaded.'
10
+
11
+ trap(:INT) { exit }
12
+
13
+ client = Workling::Clients::MemcacheQueueClient.new
14
+
15
+ begin
16
+ client.connect
17
+ client.reset
18
+
19
+ client.stats # do this so that connection is shown as established below.
20
+
21
+ puts "Queue state:"
22
+ pp client.inspect
23
+ pp "Active?: #{client.active?}"
24
+ pp "Read Only?: #{client.readonly?}"
25
+ puts ""
26
+ puts "Servers:"
27
+ pp client.servers
28
+ puts ""
29
+ puts "Queue stats:"
30
+ pp client.stats
31
+
32
+ puts "\nThread Stats:"
33
+ pp Thread.list
34
+ ensure
35
+ puts '** Exiting'
36
+ client.close
37
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: derfred-workling
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.9.1
4
+ version: 0.4.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rany Keddo
@@ -26,6 +26,49 @@ files:
26
26
  - VERSION.yml
27
27
  - README.markdown
28
28
  - TODO.markdown
29
+ - lib/cattr_accessor.rb
30
+ - lib/mattr_accessor.rb
31
+ - lib/rude_q/client.rb
32
+ - lib/workling/base.rb
33
+ - lib/workling/clients/amqp_client.rb
34
+ - lib/workling/clients/amqp_exchange_client.rb
35
+ - lib/workling/clients/base.rb
36
+ - lib/workling/clients/memcache_queue_client.rb
37
+ - lib/workling/clients/sqs_client.rb
38
+ - lib/workling/clients/xmpp_client.rb
39
+ - lib/workling/discovery.rb
40
+ - lib/workling/remote/invokers/amqp_single_subscriber.rb
41
+ - lib/workling/remote/invokers/base.rb
42
+ - lib/workling/remote/invokers/basic_poller.rb
43
+ - lib/workling/remote/invokers/eventmachine_subscriber.rb
44
+ - lib/workling/remote/invokers/looped_subscriber.rb
45
+ - lib/workling/remote/invokers/thread_pool_poller.rb
46
+ - lib/workling/remote/invokers/threaded_poller.rb
47
+ - lib/workling/remote/runners/amqp_exchange_runner.rb
48
+ - lib/workling/remote/runners/backgroundjob_runner.rb
49
+ - lib/workling/remote/runners/base.rb
50
+ - lib/workling/remote/runners/client_runner.rb
51
+ - lib/workling/remote/runners/not_remote_runner.rb
52
+ - lib/workling/remote/runners/not_runner.rb
53
+ - lib/workling/remote/runners/rudeq_runner.rb
54
+ - lib/workling/remote/runners/spawn_runner.rb
55
+ - lib/workling/remote/runners/starling_runner.rb
56
+ - lib/workling/remote.rb
57
+ - lib/workling/return/store/base.rb
58
+ - lib/workling/return/store/iterator.rb
59
+ - lib/workling/return/store/memory_return_store.rb
60
+ - lib/workling/return/store/rudeq_return_store.rb
61
+ - lib/workling/return/store/starling_return_store.rb
62
+ - lib/workling/routing/base.rb
63
+ - lib/workling/routing/class_and_method_routing.rb
64
+ - lib/workling/routing/static_routing.rb
65
+ - lib/workling/rudeq/client.rb
66
+ - lib/workling/rudeq/poller.rb
67
+ - lib/workling/rudeq.rb
68
+ - lib/workling.rb
69
+ - lib/workling_server.rb
70
+ - script/bj_invoker.rb
71
+ - script/starling_status.rb
29
72
  has_rdoc: true
30
73
  homepage: http://github.com/elecnix/workling
31
74
  post_install_message: