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,74 @@
1
+ module Qwirk
2
+
3
+ # Defines some default marshaling strategies for use in marshaling/unmarshaling objects
4
+ # written and read via jms. Implementing classes must define the following methods:
5
+ #
6
+ # # Return symbol
7
+ # # :text if session.create_text_message should be used to generate the JMS message
8
+ # # :bytes if session.create_bytes_message should be used to generate the JMS message
9
+ # def marshal_type
10
+ # # Return either :text or :bytes
11
+ # :text
12
+ # end
13
+ #
14
+ # # Defines the conversion to wire format by the publisher of the message
15
+ # def marshal(object)
16
+ # # Operate on object and convert to message format
17
+ # end
18
+ #
19
+ # # Defines the conversion from wire format by the consumer of the message
20
+ # def unmarshal(msg)
21
+ # # Operate on message to convert it from wire protocol back to object format
22
+ # end
23
+ module MarshalStrategy
24
+
25
+ @options = {}
26
+
27
+ def self.find(marshaler)
28
+ if marshaler.nil?
29
+ return Ruby
30
+ else
31
+ val = @options[marshaler.to_sym]
32
+ return val if val
33
+ end
34
+ raise "Invalid marshal strategy: #{marshaler}"
35
+ end
36
+
37
+ def self.registered?(marshaler)
38
+ @options.has_key?(marshaler.to_sym)
39
+ end
40
+
41
+ # Allow user-defined marshal strategies. It can either be passed a hash of sym => marshaler or a list of marshalers
42
+ # that define the to_sym method which will be used as the key.
43
+ def self.register(*marshalers)
44
+ if marshalers.size == 1 && marshalers[0].kind_of?(Hash)
45
+ marshalers[0].each do |key, marshaler|
46
+ raise "Invalid marshal strategy: #{marshaler}" unless valid?(marshaler)
47
+ @options[key] = marshaler
48
+ end
49
+ else
50
+ marshalers.each do |marshaler|
51
+ raise "Invalid marshal strategy: #{marshaler}" unless valid?(marshaler) && marshaler.respond_to?(:to_sym)
52
+ @options[marshaler.to_sym] = marshaler
53
+ end
54
+ end
55
+ end
56
+
57
+ def self.unregister(sym)
58
+ @options.delete(sym)
59
+ end
60
+
61
+ def self.valid?(marshaler)
62
+ return marshaler.respond_to?(:marshal_type) &&
63
+ marshaler.respond_to?(:marshal) &&
64
+ marshaler.respond_to?(:unmarshal)
65
+ end
66
+ end
67
+ end
68
+
69
+ require 'qwirk/marshal_strategy/bson'
70
+ require 'qwirk/marshal_strategy/json'
71
+ require 'qwirk/marshal_strategy/none'
72
+ require 'qwirk/marshal_strategy/ruby'
73
+ require 'qwirk/marshal_strategy/string'
74
+ require 'qwirk/marshal_strategy/yaml'
@@ -0,0 +1,37 @@
1
+ module Qwirk
2
+ module MarshalStrategy
3
+ module BSON
4
+ extend self
5
+
6
+ def marshal_type
7
+ :bytes
8
+ end
9
+
10
+ def to_sym
11
+ :bson
12
+ end
13
+
14
+ begin
15
+ require 'bson'
16
+ def marshal(object)
17
+ ::BSON.serialize(object).to_s
18
+ end
19
+
20
+ def unmarshal(msg)
21
+ ::BSON.deserialize(msg)
22
+ end
23
+
24
+ rescue LoadError => e
25
+ def marshal(object)
26
+ raise 'Error: BSON marshaling specified but bson gem has not been installed'
27
+ end
28
+
29
+ def unmarshal(msg)
30
+ raise 'Error: BSON marshaling specified but bson gem has not been installed'
31
+ end
32
+ end
33
+
34
+ MarshalStrategy.register(self)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ module Qwirk
2
+ module MarshalStrategy
3
+ module JSON
4
+ extend self
5
+
6
+ def marshal_type
7
+ :text
8
+ end
9
+
10
+ def to_sym
11
+ :json
12
+ end
13
+
14
+ begin
15
+ require 'json'
16
+ def marshal(object)
17
+ object.to_json
18
+ end
19
+
20
+ def unmarshal(msg)
21
+ ::JSON::Parser.new(msg).parse
22
+ end
23
+
24
+ rescue LoadError => e
25
+ def marshal(object)
26
+ raise 'Error: JSON marshaling specified but json gem has not been installed'
27
+ end
28
+
29
+ def unmarshal(msg)
30
+ raise 'Error: JSON marshaling specified but json gem has not been installed'
31
+ end
32
+ end
33
+
34
+ MarshalStrategy.register(self)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,26 @@
1
+ module Qwirk
2
+ module MarshalStrategy
3
+ # Should only be used with InMem strategy
4
+ module None
5
+ extend self
6
+
7
+ def marshal_type
8
+ :bytes
9
+ end
10
+
11
+ def to_sym
12
+ :none
13
+ end
14
+
15
+ def marshal(object)
16
+ object
17
+ end
18
+
19
+ def unmarshal(msg)
20
+ msg
21
+ end
22
+
23
+ MarshalStrategy.register(self)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Qwirk
2
+ module MarshalStrategy
3
+ module Ruby
4
+ extend self
5
+
6
+ def marshal_type
7
+ :bytes
8
+ end
9
+
10
+ def to_sym
11
+ :ruby
12
+ end
13
+
14
+ def marshal(object)
15
+ ::Marshal.dump(object)
16
+ end
17
+
18
+ def unmarshal(msg)
19
+ msg = ::String.from_java_bytes(msg) unless msg.kind_of?(::String)
20
+ ::Marshal.load(msg)
21
+ end
22
+
23
+ MarshalStrategy.register(self)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module Qwirk
2
+ module MarshalStrategy
3
+ module String
4
+ extend self
5
+
6
+ def marshal_type
7
+ :text
8
+ end
9
+
10
+ def to_sym
11
+ :string
12
+ end
13
+
14
+ def marshal(object)
15
+ object.to_s
16
+ end
17
+
18
+ def unmarshal(msg)
19
+ msg
20
+ end
21
+
22
+ MarshalStrategy.register(self)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module Qwirk
2
+ module MarshalStrategy
3
+ module YAML
4
+ extend self
5
+
6
+ def marshal_type
7
+ :text
8
+ end
9
+
10
+ def to_sym
11
+ :yaml
12
+ end
13
+
14
+ def marshal(object)
15
+ object.to_yaml
16
+ end
17
+
18
+ def unmarshal(msg)
19
+ ::YAML.load(msg)
20
+ end
21
+
22
+ MarshalStrategy.register(self)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,170 @@
1
+ require 'timeout'
2
+
3
+ module Qwirk
4
+ class PublishHandle
5
+ def initialize(publisher, adapter_info, start)
6
+ @producer = publisher
7
+ @adapter_info = adapter_info
8
+ @start = start
9
+ end
10
+
11
+ # Waits the given timeout for a response message on the queue.
12
+ #
13
+ # If called w/o a block:
14
+ # Returns the message
15
+ # Returns nil on timeout
16
+ # Raises RemoteException on a remote exception
17
+ #
18
+ # If called with a block, for instance:
19
+ # handle.read_response(timeout) do |response|
20
+ # response.on_message 'CharCount' do |hash|
21
+ # puts "CharCount returned #{hash.inspect}"
22
+ # end
23
+ # response.on_message 'Length', 'Reverse' do |val|
24
+ # puts "#{response.name} returned #{val}"
25
+ # end
26
+ # response.on_message 'ExceptionRaiser' do |val|
27
+ # puts "#{response.name} didn't raise an exception but returned #{val}"
28
+ # end
29
+ # response.on_timeout 'Reverse' do
30
+ # puts "Reverse has it's own timeout handler"
31
+ # end
32
+ # response.on_timeout do
33
+ # puts "#{response.name} did not respond in time"
34
+ # end
35
+ # response.on_remote_exception 'ExceptionRaiser' do
36
+ # puts "It figures that ExceptionRaiser would raise an exception"
37
+ # end
38
+ # response.on_remote_exception do |e|
39
+ # puts "#{response.name} raised an exception #{e.message}\n\t#{e.backtrace.join("\n\t")}"
40
+ # end
41
+ # end
42
+ #
43
+ # The specified blocks will be called for each response. For instance, LengthWorker#request
44
+ # might return 4 and "Length returned 4" would be displayed. If it failed to respond within the
45
+ # timeout, then "Length did no respond in time" would be displayed.
46
+ # For Workers that raise an exception, they will either be handled by their specific handler if it exists or
47
+ # the default exception handler. If that doesn't exist either, then the RemoteException will be raised for the
48
+ # whole read_response call. Timeouts will also be handled by the default timeout handler unless a specific one
49
+ # is specified. All messages must have a specific handler specified because the call won't return until all
50
+ # specified handlers either return, timeout, or return an exception.
51
+ #
52
+ def read_response(timeout, &block)
53
+ raise "Invalid call to read_response for #{@producer}, not setup for responding" unless @producer.response_options
54
+ # Creates a block for reading the responses for a given message_id (adapter_info). The block will be passed an object
55
+ # that responds to timeout_read(timeout) with a [original_message_id, response_message, worker_name] tri or nil if no message is read.
56
+ # This is used in the RPC mechanism where a publish might wait for 1 or more workers to respond.
57
+ @producer.adapter.with_response(@adapter_info) do |consumer|
58
+ if block_given?
59
+ return read_multiple_response(consumer, timeout, &block)
60
+ else
61
+ response = read_single_response(consumer, timeout)
62
+ raise response if response.kind_of?(Qwirk::RemoteException)
63
+ return response
64
+ end
65
+ end
66
+ end
67
+
68
+ #######
69
+ private
70
+ #######
71
+
72
+ def read_single_response(consumer, timeout)
73
+ leftover_timeout = @start + timeout - Time.now
74
+ message_id, response, @worker_name = consumer.timeout_read(leftover_timeout)
75
+ return response
76
+ end
77
+
78
+ def read_multiple_response(consumer, timeout, &block)
79
+ worker_response = WorkerResponse.new(@start)
80
+ yield worker_response
81
+
82
+ until worker_response.done? do
83
+ response = read_single_response(consumer, timeout)
84
+ if !response
85
+ worker_response.make_timeout_calls
86
+ return
87
+ end
88
+ if response.kind_of?(Qwirk::RemoteException)
89
+ worker_response.make_exception_call(@worker_name, response)
90
+ else
91
+ worker_response.make_message_call(@worker_name, response)
92
+ end
93
+ end
94
+ end
95
+
96
+ class WorkerResponse
97
+ attr_reader :name, :start
98
+
99
+ def initialize(start)
100
+ @start = start
101
+ @message_hash = {}
102
+ @timeout_hash = {}
103
+ @exception_hash = {}
104
+ @default_timeout_block = nil
105
+ @default_exception_block = nil
106
+ @done_array = []
107
+ end
108
+
109
+ # Msecs since publish
110
+ def msec_delta
111
+ (Time.now - @start) * 1000
112
+ end
113
+
114
+ def on_message(*names, &block)
115
+ raise 'Must explicitly define all message handlers so we know that we\'re done' if names.empty?
116
+ names.each {|name| @message_hash[name] = block}
117
+ end
118
+
119
+ def on_timeout(*names, &block)
120
+ if names.empty?
121
+ @default_timeout_block = block
122
+ else
123
+ names.each {|name| @timeout_hash[name] = block}
124
+ end
125
+ end
126
+
127
+ def on_remote_exception(*names, &block)
128
+ if names.empty?
129
+ @default_exception_block = block
130
+ else
131
+ names.each {|name| @exception_hash[name] = block}
132
+ end
133
+ @remote_exception_block = block
134
+ end
135
+
136
+ def make_message_call(name, obj)
137
+ # Give the client access to the name
138
+ @name = name
139
+ block = @message_hash[name]
140
+ block.call(obj) if block
141
+ @done_array << name
142
+ end
143
+
144
+ def done?
145
+ (@message_hash.keys - @done_array).empty?
146
+ end
147
+
148
+ def make_timeout_calls
149
+ @timeouts = @message_hash.keys - @done_array
150
+ @timeouts.each do |name|
151
+ # Give the client access to the name
152
+ @name = name
153
+ block = @timeout_hash[name] || @default_timeout_block
154
+ block.call if block
155
+ end
156
+ end
157
+
158
+ def make_exception_call(name, e)
159
+ @name = name
160
+ block = @exception_hash[name] || @default_exception_block
161
+ if block
162
+ block.call(e)
163
+ @done_array << name
164
+ else
165
+ raise e
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,67 @@
1
+ # Protocol independent class to handle Publishing
2
+ module Qwirk
3
+ class Publisher
4
+ include Rumx::Bean
5
+
6
+ #attr_reader :producer_options, :persistent, :reply_queue
7
+ attr_reader :response_options, :adapter, :marshaler
8
+
9
+ bean_attr_reader :tasks, :hash, 'Hash of the latest tasks', :hash_type => :bean
10
+
11
+ # Parameters:
12
+ # One of the following must be specified
13
+ # :queue_name => String: Name of the Queue to publish to
14
+ # :topic_name => String: Name of the Topic to publish to
15
+ # Optional:
16
+ # :time_to_live => expiration time in ms for the message (JMS)
17
+ # :persistent => true or false (defaults to false) (JMS)
18
+ # :marshal => Symbol: One of :ruby, :string, :json, :bson, :yaml or any registered types (See Qwirk::MarshalStrategy), defaults to :ruby
19
+ # :response => if true or a hash of response options, a temporary reply queue will be setup for handling responses
20
+ # :time_to_live => expiration time in ms for the response message(s) (JMS))
21
+ # :persistent => true or false for the response message(s), set to false if you don't want timed out messages ending up in the DLQ (defaults to true unless time_to_live is set)
22
+ def initialize(queue_adapter, options)
23
+ options = options.dup
24
+ @queue_name = options.delete(:queue_name)
25
+ @topic_name = options.delete(:topic_name)
26
+ raise "One of :queue_name or :topic_name must be given in #{self.class.name}" if !@queue_name && !@topic_name
27
+
28
+ @response_options = options.delete(:response)
29
+ # response_options should only be a hash or the values true or false
30
+ @response_options = {} if @response_options && !@response_options.kind_of?(Hash)
31
+
32
+ @tasks = {}
33
+ @adapter = queue_adapter.create_adapter_publisher(@queue_name, @topic_name, options, @response_options)
34
+ marshal_sym = options[:marshal] || :ruby
35
+ @marshaler = Qwirk::MarshalStrategy.find(marshal_sym)
36
+ end
37
+
38
+ # Publish the given object to the address.
39
+ def publish(object, props={})
40
+ start = Time.now
41
+ marshaled_object = @marshaler.marshal(object)
42
+ adapter_info = @adapter.publish(marshaled_object, @marshaler, nil, props)
43
+ return PublishHandle.new(self, adapter_info, start)
44
+ end
45
+
46
+ # Creates a producer/consumer pair for writing and reading responses for a given task. It will return a pair of
47
+ # [producer, consumer]. The producer will publish objects specifically for the task. The consumer is an object that responds_to
48
+ # receive which will return a [message_id, response object] and acknowledge_message which will acknowledge the
49
+ # last message read. It should also respond to stop which will interrupt any receive calls causing it to return nil.
50
+ def create_producer_consumer_pair(task)
51
+ @tasks[task.task_id] = task
52
+ @adapter.create_producer_consumer_pair(task.task_id, @marshaler)
53
+ end
54
+
55
+ def to_s
56
+ "#{self.class.name}:#{@queue_name || @topic_name}"
57
+ end
58
+
59
+ def default_fail_queue_name
60
+ Qwirk.fail_queue_name(@queue_name || @topic_name)
61
+ end
62
+
63
+ def create_fail_queue_consumer(fail_queue_name=nil)
64
+ fail_queue_name ||= default_fail_queue_name
65
+ end
66
+ end
67
+ end