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.
Files changed (58) hide show
  1. data/bin/workling_client +9 -7
  2. data/{script → contrib}/bj_invoker.rb +0 -0
  3. data/{script → contrib}/starling_status.rb +0 -0
  4. data/lib/{cattr_accessor.rb → extensions/cattr_accessor.rb} +0 -0
  5. data/lib/{mattr_accessor.rb → extensions/mattr_accessor.rb} +0 -0
  6. data/lib/workling.rb +98 -94
  7. data/lib/workling/base.rb +6 -11
  8. data/lib/workling/clients/amqp_client.rb +13 -5
  9. data/lib/workling/clients/amqp_exchange_client.rb +19 -11
  10. data/lib/workling/clients/backgroundjob_client.rb +25 -0
  11. data/lib/workling/clients/base.rb +40 -8
  12. data/lib/workling/clients/broker_base.rb +63 -0
  13. data/lib/workling/clients/memcache_queue_client.rb +24 -12
  14. data/lib/workling/clients/memory_queue_client.rb +34 -0
  15. data/lib/workling/clients/not_client.rb +14 -0
  16. data/lib/workling/clients/not_remote_client.rb +17 -0
  17. data/lib/workling/clients/spawn_client.rb +47 -0
  18. data/lib/workling/clients/sqs_client.rb +9 -8
  19. data/lib/workling/clients/thread_client.rb +18 -0
  20. data/lib/workling/clients/xmpp_client.rb +14 -4
  21. data/lib/workling/discovery.rb +1 -1
  22. data/lib/workling/invokers/amqp_single_subscriber.rb +42 -0
  23. data/lib/workling/invokers/base.rb +124 -0
  24. data/lib/workling/invokers/basic_poller.rb +38 -0
  25. data/lib/workling/invokers/eventmachine_subscriber.rb +38 -0
  26. data/lib/workling/invokers/looped_subscriber.rb +34 -0
  27. data/lib/workling/invokers/thread_pool_poller.rb +165 -0
  28. data/lib/workling/invokers/threaded_poller.rb +149 -0
  29. data/lib/workling/remote.rb +10 -41
  30. data/lib/workling/return/store/base.rb +7 -7
  31. data/lib/workling/return/store/memory_return_store.rb +0 -2
  32. data/lib/workling/return/store/starling_return_store.rb +7 -8
  33. data/lib/workling/routing/base.rb +1 -4
  34. data/lib/workling/routing/class_and_method_routing.rb +0 -2
  35. data/lib/workling/routing/static_routing.rb +0 -4
  36. data/lib/{workling_server.rb → workling_daemon.rb} +27 -25
  37. metadata +21 -28
  38. data/lib/rude_q/client.rb +0 -11
  39. data/lib/workling/remote/invokers/amqp_single_subscriber.rb +0 -45
  40. data/lib/workling/remote/invokers/base.rb +0 -124
  41. data/lib/workling/remote/invokers/basic_poller.rb +0 -41
  42. data/lib/workling/remote/invokers/eventmachine_subscriber.rb +0 -41
  43. data/lib/workling/remote/invokers/looped_subscriber.rb +0 -38
  44. data/lib/workling/remote/invokers/thread_pool_poller.rb +0 -169
  45. data/lib/workling/remote/invokers/threaded_poller.rb +0 -153
  46. data/lib/workling/remote/runners/amqp_exchange_runner.rb +0 -45
  47. data/lib/workling/remote/runners/backgroundjob_runner.rb +0 -35
  48. data/lib/workling/remote/runners/base.rb +0 -42
  49. data/lib/workling/remote/runners/client_runner.rb +0 -46
  50. data/lib/workling/remote/runners/not_remote_runner.rb +0 -23
  51. data/lib/workling/remote/runners/not_runner.rb +0 -17
  52. data/lib/workling/remote/runners/rudeq_runner.rb +0 -23
  53. data/lib/workling/remote/runners/spawn_runner.rb +0 -38
  54. data/lib/workling/remote/runners/starling_runner.rb +0 -13
  55. data/lib/workling/return/store/rudeq_return_store.rb +0 -24
  56. data/lib/workling/rudeq.rb +0 -7
  57. data/lib/workling/rudeq/client.rb +0 -17
  58. data/lib/workling/rudeq/poller.rb +0 -116
@@ -1,35 +0,0 @@
1
- require 'workling/remote/runners/base'
2
-
3
- #
4
- # Use Ara Howards BackgroundJob to run the work. BackgroundJob loads Rails once per requested Job.
5
- # It persists over the database, and there is no requirement for separate processes to be started.
6
- # Since rails has to load before each request, it takes a moment for the job to run.
7
- #
8
- module Workling
9
- module Remote
10
- module Runners
11
- class BackgroundjobRunner < Workling::Remote::Runners::Base
12
- cattr_accessor :routing
13
-
14
- def initialize
15
- BackgroundjobRunner.routing =
16
- Workling::Routing::ClassAndMethodRouting.new
17
- end
18
-
19
- # passes the job to bj by serializing the options to xml and passing them to
20
- # ./script/bj_invoker.rb, which in turn routes the deserialized args to the
21
- # appropriate worker.
22
- def run(clazz, method, options = {})
23
- stdin = @@routing.queue_for(clazz, method) +
24
- " " +
25
- options.to_xml(:indent => 0, :skip_instruct => true)
26
-
27
- Bj.submit "./script/runner ./script/bj_invoker.rb",
28
- :stdin => stdin
29
-
30
- return nil # that means nothing!
31
- end
32
- end
33
- end
34
- end
35
- end
@@ -1,42 +0,0 @@
1
- #
2
- # Base class for Workling Runners.
3
- #
4
- # Runners must subclass this and implement the method
5
- #
6
- # Workling::Remote::Runners::Base#run(clazz, method, options = {})
7
- #
8
- # which is responsible for pushing the requested job into the background. Depending
9
- # on the Runner, this may require other code to dequeue the job. The actual
10
- # invocation of the runner should be done like this:
11
- #
12
- # Workling.find(clazz, method).dispatch_to_worker_method(method, options)
13
- #
14
- # This ensures for consistent logging and handling of propagated exceptions. You can
15
- # also call the convenience method
16
- #
17
- # Workling::Remote::Runners::Base#dispatch!(clazz, method, options)
18
- #
19
- # which invokes this for you.
20
- #
21
- module Workling
22
- module Remote
23
- module Runners
24
- class Base
25
-
26
- # runner uses this to connect to a job broker
27
- cattr_accessor :client
28
-
29
- # default logger defined in Workling::Base.logger
30
- def logger
31
- Workling::Base.logger
32
- end
33
-
34
- # find the worker instance and invoke it. Invoking the worker method like this ensures for
35
- # consistent logging and handling of propagated exceptions.
36
- def dispatch!(clazz, method, options)
37
- Workling.find(clazz, method).dispatch_to_worker_method(method, options)
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,46 +0,0 @@
1
- require 'workling/remote/runners/base'
2
- require 'workling/routing/class_and_method_routing'
3
- require 'workling/clients/memcache_queue_client'
4
-
5
- #
6
- # Runs Jobs over a Client. The client should be a subclass of Workling::Client::Base.
7
- # Set the client like this:
8
- #
9
- # Workling::Remote::Runners::ClientRunner.client = Workling::Clients::AmqpClient.new
10
- #
11
- # Jobs are dispatched by requesting them on the Client. The Runner takes care of mapping of queue names to worker code.
12
- # this is done with Workling::ClassAndMethodRouting, but you can use your own by sublassing Workling::Routing.
13
- # Don’t worry about any of this if you’re not dealing directly with the queues.
14
- #
15
- # There’s a workling-client daemon that uses the configured invoker to retrieve work and dispatching these to the
16
- # responsible workers. If you intend to run this on a remote machine, then just check out your rails project
17
- # there and start up the workling client like this: ruby script/workling_client run.
18
- #
19
- module Workling
20
- module Remote
21
- module Runners
22
- class ClientRunner < Workling::Remote::Runners::Base
23
-
24
- # Routing class. Workling::Routing::ClassAndMethodRouting.new by default.
25
- cattr_accessor :routing
26
- @@routing ||= Workling::Routing::ClassAndMethodRouting.new
27
-
28
- # The workling Client class. Workling::Clients::MemcacheQueueClient.new by default.
29
- cattr_accessor :client
30
- @@client ||= Workling::Clients::MemcacheQueueClient.new
31
-
32
- # enqueues the job onto the client
33
- def run(clazz, method, options = {})
34
-
35
- # neet to connect in here as opposed to the constructor, since the EM loop is
36
- # not available there.
37
- @connected ||= self.class.client.connect
38
-
39
- self.class.client.request(@@routing.queue_for(clazz, method), options)
40
-
41
- return nil
42
- end
43
- end
44
- end
45
- end
46
- end
@@ -1,23 +0,0 @@
1
- require 'workling/remote/runners/base'
2
-
3
- #
4
- # directly dispatches to the worker method, in-process. options are first marshalled then dumped
5
- # in order to simulate the sideeffects of a remote call.
6
- #
7
- module Workling
8
- module Remote
9
- module Runners
10
- class NotRemoteRunner < Workling::Remote::Runners::Base
11
-
12
- # directly dispatches to the worker method, in-process. options are first marshalled then dumped
13
- # in order to simulate the sideeffects of a remote call.
14
- def run(clazz, method, options = {})
15
- options = Marshal.load(Marshal.dump(options)) # get this to behave more like the remote runners
16
- dispatch!(clazz, method, options)
17
-
18
- return nil # nada. niente.
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,17 +0,0 @@
1
- require 'workling/remote/runners/base'
2
-
3
- #
4
- # this does absolutely nothing, mainly for testing
5
- #
6
-
7
- module Workling
8
- module Remote
9
- module Runners
10
- class NotRunner < Workling::Remote::Runners::Base
11
- def run(clazz, method, options = {})
12
- return nil # nada. niente.
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,23 +0,0 @@
1
- require 'workling/remote/runners/base'
2
-
3
- module Workling
4
- module Remote
5
- module Runners
6
- class RudeqRunner < Workling::Remote::Runners::Base
7
- cattr_accessor :routing
8
- cattr_accessor :client
9
-
10
- def initialize
11
- RudeqRunner.client = Workling::Rudeq::Client.new
12
- RudeqRunner.routing = Workling::Routing::ClassAndMethodRouting.new
13
- end
14
-
15
- def run(clazz, method, options = {})
16
- RudeqRunner.client.set(@@routing.queue_for(clazz, method), options)
17
-
18
- return nil # empty.
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,38 +0,0 @@
1
- require 'workling/remote/runners/base'
2
-
3
- #
4
- # Run the job over the spawn plugin. Refer to the README for instructions on
5
- # installing Spawn.
6
- #
7
- # Spawn forks the entire process once for each job. This means that the job starts
8
- # with a very low latency, but takes up more memory for each job.
9
- #
10
- # It's also possible to configure Spawn to start a Thread for each job. Do this
11
- # by setting
12
- #
13
- # Workling::Remote::Runners::SpawnRunner.options = { :method => :thread }
14
- #
15
- # Have a look at the Spawn README to find out more about the characteristics of this.
16
- #
17
- module Workling
18
- module Remote
19
- module Runners
20
- class SpawnRunner < Workling::Remote::Runners::Base
21
- cattr_accessor :options
22
-
23
- # use thread for development and test modes. easier to hunt down exceptions that way.
24
- @@options = { :method => (RAILS_ENV == "test" || RAILS_ENV == "development" ? :fork : :thread) }
25
- include Spawn if Workling.spawn_installed?
26
-
27
- # dispatches to Spawn, using the :fork option.
28
- def run(clazz, method, options = {})
29
- spawn(SpawnRunner.options) do # exceptions are trapped in here.
30
- dispatch!(clazz, method, options)
31
- end
32
-
33
- return nil # that means nothing!
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,13 +0,0 @@
1
- require 'workling/remote/runners/client_runner'
2
-
3
- #
4
- # DEPRECATED. Should use ClientRunner instead.
5
- #
6
- module Workling
7
- module Remote
8
- module Runners
9
- class StarlingRunner < Workling::Remote::Runners::ClientRunner
10
- end
11
- end
12
- end
13
- end
@@ -1,24 +0,0 @@
1
- require 'workling/return/store/base'
2
- require 'workling/rudeq/client'
3
-
4
- module Workling
5
- module Return
6
- module Store
7
- class RudeqReturnStore < Base
8
- cattr_accessor :client
9
-
10
- def initialize
11
- self.class.client = Workling::Rudeq::Client.new
12
- end
13
-
14
- def set(key, value)
15
- self.class.client.set(key, value)
16
- end
17
-
18
- def get(key)
19
- self.class.client.get(key)
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,7 +0,0 @@
1
- module Workling
2
- module Rudeq
3
- def self.config
4
- @@config ||= {:queue_class => "RudeQueue"}
5
- end
6
- end
7
- end
@@ -1,17 +0,0 @@
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
@@ -1,116 +0,0 @@
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