qwirk 0.0.1

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 (154) hide show
  1. data/History.md +7 -0
  2. data/LICENSE.txt +201 -0
  3. data/README.md +180 -0
  4. data/Rakefile +34 -0
  5. data/examples/README +1 -0
  6. data/examples/activemq.xml +84 -0
  7. data/examples/advanced_requestor/README.md +15 -0
  8. data/examples/advanced_requestor/base_request_worker.rb +18 -0
  9. data/examples/advanced_requestor/char_count_worker.rb +16 -0
  10. data/examples/advanced_requestor/config.ru +24 -0
  11. data/examples/advanced_requestor/exception_raiser_worker.rb +17 -0
  12. data/examples/advanced_requestor/length_worker.rb +14 -0
  13. data/examples/advanced_requestor/print_worker.rb +14 -0
  14. data/examples/advanced_requestor/publisher.rb +49 -0
  15. data/examples/advanced_requestor/qwirk.yml +16 -0
  16. data/examples/advanced_requestor/reverse_worker.rb +14 -0
  17. data/examples/advanced_requestor/triple_worker.rb +14 -0
  18. data/examples/batch/my_batch_worker.rb +30 -0
  19. data/examples/batch/my_line_worker.rb +8 -0
  20. data/examples/qwirk.yml +20 -0
  21. data/examples/requestor/README.md +13 -0
  22. data/examples/requestor/config.ru +13 -0
  23. data/examples/requestor/qwirk_persist.yml +5 -0
  24. data/examples/requestor/requestor.rb +68 -0
  25. data/examples/requestor/reverse_echo_worker.rb +15 -0
  26. data/examples/setup.rb +13 -0
  27. data/examples/shared/README.md +24 -0
  28. data/examples/shared/config.ru +13 -0
  29. data/examples/shared/publisher.rb +49 -0
  30. data/examples/shared/qwirk_persist.yml +5 -0
  31. data/examples/shared/shared_worker.rb +16 -0
  32. data/examples/simple/README +53 -0
  33. data/examples/simple/bar_worker.rb +10 -0
  34. data/examples/simple/baz_worker.rb +10 -0
  35. data/examples/simple/config.ru +14 -0
  36. data/examples/simple/publisher.rb +49 -0
  37. data/examples/simple/qwirk_persist.yml +4 -0
  38. data/examples/simple/tmp/kahadb/db-1.log +0 -0
  39. data/examples/simple/tmp/kahadb/db.data +0 -0
  40. data/examples/simple/tmp/kahadb/db.redo +0 -0
  41. data/examples/task/README +47 -0
  42. data/examples/task/config.ru +14 -0
  43. data/examples/task/foo_worker.rb +10 -0
  44. data/examples/task/messages.out +1000 -0
  45. data/examples/task/publisher.rb +25 -0
  46. data/examples/task/qwirk_persist.yml +5 -0
  47. data/examples/task/task.rb +36 -0
  48. data/lib/qwirk.rb +63 -0
  49. data/lib/qwirk/adapter.rb +45 -0
  50. data/lib/qwirk/base_worker.rb +96 -0
  51. data/lib/qwirk/batch.rb +4 -0
  52. data/lib/qwirk/batch/acquire_file_strategy.rb +47 -0
  53. data/lib/qwirk/batch/active_record.rb +3 -0
  54. data/lib/qwirk/batch/active_record/batch_job.rb +111 -0
  55. data/lib/qwirk/batch/active_record/failed_record.rb +5 -0
  56. data/lib/qwirk/batch/active_record/outstanding_record.rb +6 -0
  57. data/lib/qwirk/batch/file_status_strategy.rb +86 -0
  58. data/lib/qwirk/batch/file_worker.rb +228 -0
  59. data/lib/qwirk/batch/job_status.rb +29 -0
  60. data/lib/qwirk/batch/parse_file_strategy.rb +48 -0
  61. data/lib/qwirk/engine.rb +9 -0
  62. data/lib/qwirk/loggable.rb +23 -0
  63. data/lib/qwirk/manager.rb +140 -0
  64. data/lib/qwirk/marshal_strategy.rb +74 -0
  65. data/lib/qwirk/marshal_strategy/bson.rb +37 -0
  66. data/lib/qwirk/marshal_strategy/json.rb +37 -0
  67. data/lib/qwirk/marshal_strategy/none.rb +26 -0
  68. data/lib/qwirk/marshal_strategy/ruby.rb +26 -0
  69. data/lib/qwirk/marshal_strategy/string.rb +25 -0
  70. data/lib/qwirk/marshal_strategy/yaml.rb +25 -0
  71. data/lib/qwirk/publish_handle.rb +170 -0
  72. data/lib/qwirk/publisher.rb +67 -0
  73. data/lib/qwirk/queue_adapter.rb +3 -0
  74. data/lib/qwirk/queue_adapter/active_mq.rb +13 -0
  75. data/lib/qwirk/queue_adapter/active_mq/publisher.rb +12 -0
  76. data/lib/qwirk/queue_adapter/active_mq/worker_config.rb +16 -0
  77. data/lib/qwirk/queue_adapter/in_mem.rb +7 -0
  78. data/lib/qwirk/queue_adapter/in_mem/factory.rb +45 -0
  79. data/lib/qwirk/queue_adapter/in_mem/publisher.rb +98 -0
  80. data/lib/qwirk/queue_adapter/in_mem/queue.rb +88 -0
  81. data/lib/qwirk/queue_adapter/in_mem/reply_queue.rb +56 -0
  82. data/lib/qwirk/queue_adapter/in_mem/topic.rb +48 -0
  83. data/lib/qwirk/queue_adapter/in_mem/worker.rb +63 -0
  84. data/lib/qwirk/queue_adapter/in_mem/worker_config.rb +59 -0
  85. data/lib/qwirk/queue_adapter/jms.rb +50 -0
  86. data/lib/qwirk/queue_adapter/jms/connection.rb +42 -0
  87. data/lib/qwirk/queue_adapter/jms/consumer.rb +37 -0
  88. data/lib/qwirk/queue_adapter/jms/publisher.rb +126 -0
  89. data/lib/qwirk/queue_adapter/jms/worker.rb +89 -0
  90. data/lib/qwirk/queue_adapter/jms/worker_config.rb +38 -0
  91. data/lib/qwirk/remote_exception.rb +42 -0
  92. data/lib/qwirk/request_worker.rb +62 -0
  93. data/lib/qwirk/task.rb +177 -0
  94. data/lib/qwirk/task.rb.sav +194 -0
  95. data/lib/qwirk/version.rb +3 -0
  96. data/lib/qwirk/worker.rb +222 -0
  97. data/lib/qwirk/worker_config.rb +187 -0
  98. data/lib/rails/generators/qwirk/qwirk_generator.rb +82 -0
  99. data/lib/rails/generators/qwirk/templates/initializer.rb +6 -0
  100. data/lib/rails/generators/qwirk/templates/migration.rb +9 -0
  101. data/lib/rails/generators/qwirk/templates/schema.rb +28 -0
  102. data/lib/rails/railties/tasks.rake +8 -0
  103. data/lib/tasks/qwirk_tasks.rake +4 -0
  104. data/test/base_test.rb +248 -0
  105. data/test/database.yml +14 -0
  106. data/test/dummy/Rakefile +7 -0
  107. data/test/dummy/app/controllers/application_controller.rb +3 -0
  108. data/test/dummy/app/helpers/application_helper.rb +2 -0
  109. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  110. data/test/dummy/config.ru +4 -0
  111. data/test/dummy/config/application.rb +45 -0
  112. data/test/dummy/config/boot.rb +10 -0
  113. data/test/dummy/config/database.yml +22 -0
  114. data/test/dummy/config/environment.rb +5 -0
  115. data/test/dummy/config/environments/development.rb +26 -0
  116. data/test/dummy/config/environments/production.rb +49 -0
  117. data/test/dummy/config/environments/test.rb +35 -0
  118. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  119. data/test/dummy/config/initializers/inflections.rb +10 -0
  120. data/test/dummy/config/initializers/mime_types.rb +5 -0
  121. data/test/dummy/config/initializers/secret_token.rb +7 -0
  122. data/test/dummy/config/initializers/session_store.rb +8 -0
  123. data/test/dummy/config/locales/en.yml +5 -0
  124. data/test/dummy/config/routes.rb +58 -0
  125. data/test/dummy/log/development.log +0 -0
  126. data/test/dummy/log/production.log +0 -0
  127. data/test/dummy/log/server.log +0 -0
  128. data/test/dummy/log/test.log +0 -0
  129. data/test/dummy/public/404.html +26 -0
  130. data/test/dummy/public/422.html +26 -0
  131. data/test/dummy/public/500.html +26 -0
  132. data/test/dummy/public/favicon.ico +0 -0
  133. data/test/dummy/public/javascripts/application.js +2 -0
  134. data/test/dummy/public/javascripts/controls.js +965 -0
  135. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  136. data/test/dummy/public/javascripts/effects.js +1123 -0
  137. data/test/dummy/public/javascripts/prototype.js +6001 -0
  138. data/test/dummy/public/javascripts/rails.js +191 -0
  139. data/test/dummy/script/rails +6 -0
  140. data/test/integration/navigation_test.rb +7 -0
  141. data/test/jms.yml +9 -0
  142. data/test/jms_fail_test.rb +149 -0
  143. data/test/jms_requestor_block_test.rb +278 -0
  144. data/test/jms_requestor_test.rb +238 -0
  145. data/test/jms_test.rb +287 -0
  146. data/test/marshal_strategy_test.rb +62 -0
  147. data/test/support/integration_case.rb +5 -0
  148. data/test/test_helper.rb +7 -0
  149. data/test/test_helper.rbold +22 -0
  150. data/test/test_helper_active_record.rb +61 -0
  151. data/test/unit/qwirk/batch/acquire_file_strategy_test.rb +101 -0
  152. data/test/unit/qwirk/batch/active_record/batch_job_test.rb +35 -0
  153. data/test/unit/qwirk/batch/parse_file_strategy_test.rb +49 -0
  154. metadata +366 -0
@@ -0,0 +1,3 @@
1
+ require 'qwirk/queue_adapter/in_mem'
2
+ require 'qwirk/queue_adapter/jms'
3
+ require 'qwirk/queue_adapter/active_mq'
@@ -0,0 +1,13 @@
1
+ require 'activemq'
2
+ require 'qwirk/queue_adapter/active_mq/publisher'
3
+ require 'qwirk/queue_adapter/active_mq/worker_config'
4
+
5
+ module Qwirk
6
+ module QueueAdapter
7
+ module ActiveMQ
8
+ def self.init(config)
9
+ JMS.init(config)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Qwirk
2
+ module QueueAdapter
3
+ module ActiveMQ
4
+ class Publisher < JMS::Publisher
5
+ def initialize(queue_adapter, queue_name, topic_name, options, response_options)
6
+ topic_name = "VirtualTopic.#{topic_name}" if topic_name
7
+ super(queue_adapter, queue_name, topic_name, options, response_options)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ # Handle Messaging and Queuing using ActiveMQ
2
+ module Qwirk
3
+ module QueueAdapter
4
+ module ActiveMQ
5
+ class WorkerConfig < JMS::WorkerConfig
6
+ def initialize(queue_adapter, parent, queue_name, topic_name, options, response_options)
7
+ if topic_name
8
+ queue_name = "Consumer.#{parent.name}.VirtualTopic.#{topic_name}"
9
+ topic_name = nil
10
+ end
11
+ super(queue_adapter, parent, queue_name, topic_name, options, response_options)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ require 'qwirk/queue_adapter/in_mem/factory'
2
+ require 'qwirk/queue_adapter/in_mem/publisher'
3
+ require 'qwirk/queue_adapter/in_mem/queue'
4
+ require 'qwirk/queue_adapter/in_mem/reply_queue'
5
+ require 'qwirk/queue_adapter/in_mem/topic'
6
+ require 'qwirk/queue_adapter/in_mem/worker_config'
7
+ require 'qwirk/queue_adapter/in_mem/worker'
@@ -0,0 +1,45 @@
1
+ module Qwirk
2
+ module QueueAdapter
3
+ module InMem
4
+ module Factory
5
+ class << self
6
+ def init
7
+ @queue_hash = {}
8
+ @topic_hash = {}
9
+ @queue_hash_mutex = Mutex.new
10
+ @topic_hash_mutex = Mutex.new
11
+ end
12
+
13
+ def get_worker_queue(worker_name, queue_name, topic_name, queue_max_size)
14
+ if queue_name
15
+ @queue_hash_mutex.synchronize do
16
+ queue = @queue_hash[queue_name] ||= Queue.new(queue_name)
17
+ queue.max_size = queue_max_size
18
+ return queue
19
+ end
20
+ else
21
+ @topic_hash_mutex.synchronize do
22
+ topic = @topic_hash[topic_name] ||= Topic.new(topic_name)
23
+ return topic.get_worker_queue(worker_name, queue_max_size)
24
+ end
25
+ end
26
+ end
27
+
28
+ def get_publisher_queue(queue_name, topic_name)
29
+ if queue_name
30
+ @queue_hash_mutex.synchronize do
31
+ return @queue_hash[queue_name] ||= Queue.new(queue_name)
32
+ end
33
+ else
34
+ @topic_hash_mutex.synchronize do
35
+ return @topic_hash[topic_name] ||= Topic.new(topic_name)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ Factory.init
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,98 @@
1
+ module Qwirk
2
+ module QueueAdapter
3
+ module InMem
4
+ class Publisher
5
+
6
+ def initialize(queue_adapter, queue_name, topic_name, options, response_options)
7
+ @queue_name, @topic_name, @options, @response_options = queue_name, topic_name, options, response_options
8
+ @queue = Factory.get_publisher_queue(queue_name, topic_name)
9
+ end
10
+
11
+ def default_marshal_sym
12
+ :none
13
+ end
14
+
15
+ # Publish the given object and return the reply_queue as the adapter_info.
16
+ def publish(marshaled_object, marshaler, task_id, props)
17
+ # Since we're in-memory, we'll just unmarshal the object so there is less info to carry around
18
+ object = marshaler.unmarshal(marshaled_object)
19
+ reply_queue = nil
20
+ if @response_options
21
+ reply_queue = ReplyQueue.new("#{@queue}:#{object.to_s}")
22
+ end
23
+ @queue.write([object, reply_queue])
24
+ # Return the object to get sent to with_response below.
25
+ return reply_queue
26
+ end
27
+
28
+ # See Qwirk::PublishHandle#read_response for the requirements for this method.
29
+ def with_response(reply_queue, &block)
30
+ raise "Could not find reply_queue for #{@queue}" unless reply_queue
31
+ yield reply_queue
32
+ end
33
+
34
+ # See Qwirk::Publisher#create_producer_consumer_pair for the requirements for this method
35
+ def create_producer_consumer_pair(task_id, marshaler)
36
+ consumer_queue = Queue.new("#{@queue}:#{task_id}")
37
+ consumer_queue.max_size = @response_options[:queue_max_size] || 100
38
+ producer = MyTaskProducer.new(@queue, consumer_queue, marshaler, @response_options)
39
+ consumer = MyTaskConsumer.new(@queue, consumer_queue)
40
+ return producer, consumer
41
+ end
42
+
43
+ def create_fail_producer_consumer_pair(task_id, marshaler)
44
+ consumer_queue = Queue.new("#{@queue}Fail:#{task_id}")
45
+ # TODO: Unlimitied queue or some form of exception on maximum
46
+ consumer_queue.max_size = -1
47
+ producer = MyTaskProducer.new(@queue, consumer_queue, marshaler, {})
48
+ consumer = MyTaskConsumer.new(@queue, consumer_queue)
49
+ return producer, consumer
50
+ end
51
+
52
+ private
53
+
54
+ class MyTaskProducer
55
+ def initialize(producer_queue, consumer_queue, marshaler, response_options)
56
+ @producer_queue = producer_queue
57
+ @consumer_queue = consumer_queue
58
+ @marshaler = marshaler
59
+ @response_options = response_options
60
+ end
61
+
62
+ def send(marshaled_object)
63
+ object = @marshaler.unmarshal(marshaled_object)
64
+ @producer_queue.write([object, @consumer_queue])
65
+ return object.object_id
66
+ end
67
+ end
68
+
69
+ class MyTaskConsumer
70
+ attr_reader :stopped
71
+
72
+ def initialize(producer_queue, consumer_queue)
73
+ @producer_queue = producer_queue
74
+ @consumer_queue = consumer_queue
75
+ @stopped = false
76
+ end
77
+
78
+ def receive
79
+ message_id, response, worker_name = @consumer_queue.read(self)
80
+ return nil unless response
81
+ return [message_id, response]
82
+ end
83
+
84
+ def acknowledge_message
85
+ end
86
+
87
+ def stop
88
+ return if @stopped
89
+ Qwirk.logger.info "Stopping Task worker #{@consumer_queue}"
90
+ # Don't clobber the session before a reply
91
+ @producer_queue.interrupt_read
92
+ @stopped = true
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,88 @@
1
+ module Qwirk
2
+ module QueueAdapter
3
+ module InMem
4
+
5
+ class Queue
6
+ # TODO: Look into reimplementing using a Ruby Queue which is probably better performant
7
+ # Size of the queue before it write-blocks. If 0, messages will be dropped. If -1, then it's unlimited.
8
+ # TODO: Should implement a queue_full_strategy which would be publish_block, drop_oldest, drop_newest
9
+ attr_accessor :name, :max_size
10
+
11
+ def initialize(name)
12
+ @name = name
13
+ @max_size = 0
14
+ @outstanding_hash_mutex = Mutex.new
15
+ @read_condition = ConditionVariable.new
16
+ @write_condition = ConditionVariable.new
17
+ @stop_condition = ConditionVariable.new
18
+ @array = []
19
+ @stopped = false
20
+ end
21
+
22
+ def size
23
+ @array.size
24
+ end
25
+
26
+ def stop
27
+ @stopped = true
28
+ @outstanding_hash_mutex.synchronize do
29
+ @write_condition.broadcast
30
+ until @array.empty?
31
+ @stop_condition.wait(@outstanding_hash_mutex)
32
+ end
33
+ @read_condition.broadcast
34
+ end
35
+ end
36
+
37
+ def interrupt_read
38
+ @outstanding_hash_mutex.synchronize do
39
+ @read_condition.broadcast
40
+ end
41
+ end
42
+
43
+ # Block read until a message or we get stopped. stoppable is an object that responds to stopped (a worker or some kind of consumer)
44
+ def read(stoppable)
45
+ @outstanding_hash_mutex.synchronize do
46
+ until @stopped || stoppable.stopped do
47
+ unless @array.empty?
48
+ @write_condition.signal
49
+ return @array.shift
50
+ end
51
+ @read_condition.wait(@outstanding_hash_mutex)
52
+ end
53
+ return if stoppable.stopped
54
+ # We're not persistent, so even though we're stopped we're going to allow our stoppables to keep reading until the queue's empty
55
+ unless @array.empty?
56
+ @stop_condition.signal
57
+ return @array.shift
58
+ end
59
+ end
60
+ return nil
61
+ end
62
+
63
+ def write(obj)
64
+ @outstanding_hash_mutex.synchronize do
65
+ # We just drop the message if no workers have been configured yet
66
+ while !@stopped
67
+ if @max_size == 0
68
+ Qwirk.logger.warn "No worker for queue #{@name}, dropping message #{obj.inspect}"
69
+ return
70
+ end
71
+ if @max_size < 0 || @array.size < @max_size
72
+ @array << obj
73
+ @read_condition.signal
74
+ return
75
+ end
76
+ # TODO: Let's allow various write_full_modes such as :block, :remove_oldest, ? (Currently only blocks)
77
+ @write_condition.wait(@outstanding_hash_mutex)
78
+ end
79
+ end
80
+ end
81
+
82
+ def to_s
83
+ "queue:#{@name}"
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,56 @@
1
+ module Qwirk
2
+ module QueueAdapter
3
+ module InMem
4
+
5
+ class ReplyQueue
6
+ def initialize(name)
7
+ @name = name
8
+ @outstanding_hash_mutex = Mutex.new
9
+ @read_condition = ConditionVariable.new
10
+ @array = []
11
+ end
12
+
13
+ def timeout_read(timeout)
14
+ @outstanding_hash_mutex.synchronize do
15
+ return @array.shift unless @array.empty?
16
+ timed_read_condition_wait(timeout)
17
+ return @array.shift
18
+ end
19
+ return nil
20
+ end
21
+
22
+ def write(obj)
23
+ @outstanding_hash_mutex.synchronize do
24
+ @array << obj
25
+ @read_condition.signal
26
+ return
27
+ end
28
+ end
29
+
30
+ def to_s
31
+ "reply_queue:#{@name}"
32
+ end
33
+
34
+ #######
35
+ private
36
+ #######
37
+
38
+ if RUBY_PLATFORM == 'jruby' || RUBY_VERSION[0,3] != '1.8'
39
+ def timed_read_condition_wait(timeout)
40
+ # This method not available in MRI 1.8
41
+ @read_condition.wait(@outstanding_hash_mutex, timeout)
42
+ end
43
+ else
44
+ require 'timeout'
45
+ def timed_read_condition_wait(timeout)
46
+ Timeout.timeout(timeout) do
47
+ @read_condition.wait(@outstanding_hash_mutex)
48
+ end
49
+ rescue Timeout::Error => e
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,48 @@
1
+ module Qwirk
2
+ module QueueAdapter
3
+ module InMem
4
+
5
+ class Topic
6
+ def initialize(name)
7
+ @name = name
8
+ @outstanding_hash_mutex = Mutex.new
9
+ @worker_hash = {}
10
+ @stopped = false
11
+ end
12
+
13
+ def get_worker_queue(worker_name, queue_max_size)
14
+ @outstanding_hash_mutex.synchronize do
15
+ queue = @worker_hash[worker_name] ||= Queue.new("#{@name}:#{worker_name}")
16
+ queue.max_size = queue_max_size
17
+ return queue
18
+ end
19
+ end
20
+
21
+ def stop
22
+ @stopped = true
23
+ @worker_hash.each_value do |queue|
24
+ queue.stop
25
+ end
26
+ end
27
+
28
+ def read
29
+ raise "topic should not have been read for #{name}"
30
+ end
31
+
32
+ def write(obj)
33
+ @outstanding_hash_mutex.synchronize do
34
+ @worker_hash.each_value do |queue|
35
+ if !@stopped
36
+ queue.write(obj)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def to_s
43
+ "topic:#{@name}"
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,63 @@
1
+ # Handle Messaging and Queuing using JMS
2
+ module Qwirk
3
+ module QueueAdapter
4
+ module InMem
5
+ class Worker
6
+ attr_reader :stopped
7
+
8
+ def initialize(name, marshaler, queue, queue_name, topic_name)
9
+ @name = name
10
+ @marshaler = marshaler
11
+ @queue = queue
12
+ @queue_name = queue_name
13
+ @topic_name = topic_name
14
+ end
15
+
16
+ def receive_message
17
+ message, @reply_queue = @queue.read(self)
18
+ return message
19
+ end
20
+
21
+ def acknowledge_message(message)
22
+ end
23
+
24
+ def send_response(original_message, marshaled_object)
25
+ # We unmarshal so our workers get consistent messages regardless of the adapter
26
+ do_send_response(original_message, @marshaler.unmarshal(marshaled_object))
27
+ end
28
+
29
+ def send_exception(original_message, e)
30
+ # TODO: I think exceptions should be recreated fully so no need for marshal/unmarshal?
31
+ do_send_response(original_message, Qwirk::RemoteException.new(e))
32
+ end
33
+
34
+ def message_to_object(msg)
35
+ # The publisher has already unmarshaled the object to save hassle here.
36
+ return msg
37
+ end
38
+
39
+ def handle_failure(message, fail_queue_name)
40
+ # TODO: Mode for persisting to flat file?
41
+ Qwirk.logger.warn("Dropping message that failed: #{message}")
42
+ end
43
+
44
+ def stop
45
+ return if @stopped
46
+ @stopped = true
47
+ Qwirk.logger.debug { "Stopping #{self}" }
48
+ @queue.interrupt_read
49
+ end
50
+
51
+ ## End of required override methods for worker adapter
52
+ private
53
+
54
+ def do_send_response(original_message, object)
55
+ puts "Returning #{object} to queue #{@reply_queue}"
56
+ return unless @reply_queue
57
+ @reply_queue.write([original_message.object_id, object, @name])
58
+ return true
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end