ruote-stomp 2.2.0.a

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/CHANGELOG.txt ADDED
@@ -0,0 +1,10 @@
1
+
2
+ = ruote-stomp
3
+
4
+
5
+ == ruote-stomp - 2.2.0 released ?
6
+
7
+ - work has just begun, porting from ruote-amqp
8
+
9
+
10
+
data/CREDITS.txt ADDED
@@ -0,0 +1,32 @@
1
+
2
+ = CREDITS
3
+
4
+ (probably incomplete, don't hesitate to tell us if a mention is missing)
5
+
6
+ == AUTHORS
7
+
8
+ * Kit Plummer - http://kitplummer.github.com
9
+
10
+ == AUTHORS (from ruote-amqp)
11
+
12
+ * Kenneth Kalmer - http://www.opensourcery.co.za/
13
+ * John Mettraux - https://github.com/jmettraux
14
+
15
+
16
+ == CONTRIBUTORS (from ruote-amqp)
17
+
18
+ * Mario Camou
19
+ * Sean Johnson - https://github.com/belucid
20
+ * Victor Liu - https://github.com/pennymax
21
+ * weifeng - https://github.com/weifeng365
22
+ * David Greaves - https://github.com/lbt
23
+ * Hartog C. de Mik - https://github.com/coffeeaddict
24
+ * Torsten Schoenebaum - https://github.com/tosch
25
+ * Jordan Ritter - https://github.com/jpr5
26
+ * Charles Magid - https://github.com/ChasManRors
27
+ * Marc Mauger - https://github.com/simianarmy
28
+ * Jason - https://github.com/asm
29
+
30
+
31
+ == FEEDBACK
32
+
data/PostInstall.txt ADDED
@@ -0,0 +1,12 @@
1
+
2
+ For more information on ruote-stomp, see http://github.com/maestrodev/ruote-stomp
3
+
4
+ Please note that this gem requires access to an Stomp broker and a good
5
+ understanding of Stomp and remote participants in general.
6
+
7
+ Join us in #ruote on Freenode or on the openwfe-users Google Group to discuss
8
+ it's uses.
9
+
10
+ You might also want to look at daemon-kit for help with writing external
11
+ participants that communicate with ruote via Stomp.
12
+
data/README.rdoc ADDED
@@ -0,0 +1,77 @@
1
+
2
+ = ruote-stomp
3
+
4
+ * http://github.com/kitplummer/ruote-stomp
5
+
6
+ == DESCRIPTION:
7
+
8
+ ruote-stomp provides a Stomp participant/listener pair that allows you to
9
+ distribute workitems out to Stomp consumers for processing, as well as launching
10
+ processes over Stomp.
11
+
12
+ To learn more about remote participants in ruote please see
13
+ http://ruote.rubyforge.org/part_implementations.html
14
+
15
+ == FEATURES/PROBLEMS:
16
+
17
+ * Flexible participant for sending workitems
18
+ * Flexible receiver for receiving replies
19
+ * Flexible launch item listener for launching processes over Stomp
20
+ * Fully evented (thanks to the stomp gem)
21
+
22
+ == SYNOPSIS:
23
+
24
+ Please review the code for information (rdocs to be updated soon.)
25
+
26
+ == REQUIREMENTS:
27
+
28
+ * ruote[http://ruote.rubyforge.org] 2.2.0 or later
29
+ * stomp[https://gitorious.org/stomp] 1.1.8 or later
30
+ * a server that supports Stomp (stompserver, ActiveMQ, RabbitMQ)
31
+
32
+ == INSTALL:
33
+
34
+ Please be sure to have read the requirements section above
35
+
36
+ * sudo gem install ruote-stomp
37
+
38
+ == TESTS:
39
+
40
+ To run the tests you need the following requirements met, or the testing environment
41
+ will fail horribly (or simply get stuck without output).
42
+
43
+ === Stomp server
44
+
45
+ I've tested it with stompserver and ActiveMQ.
46
+
47
+ I'll work on getting the Ruby stompserver setup to start/shutdown with the tests.
48
+
49
+ == DAEMON-KIT:
50
+
51
+ Will work on adding Daemon-Kit support for ruote-stomp next. :)
52
+
53
+ == LICENSE:
54
+
55
+ (The MIT License)
56
+
57
+ Copyright (c) 2010-2011 Kit Plummer (and Kenneth Kalmer for
58
+ ruote-amqp, which this works is based on)
59
+
60
+ Permission is hereby granted, free of charge, to any person obtaining
61
+ a copy of this software and associated documentation files (the
62
+ 'Software'), to deal in the Software without restriction, including
63
+ without limitation the rights to use, copy, modify, merge, publish,
64
+ distribute, sublicense, and/or sell copies of the Software, and to
65
+ permit persons to whom the Software is furnished to do so, subject to
66
+ the following conditions:
67
+
68
+ The above copyright notice and this permission notice shall be
69
+ included in all copies or substantial portions of the Software.
70
+
71
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
72
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
73
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
74
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
75
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
76
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
77
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,101 @@
1
+
2
+ $:.unshift('.') # 1.9.2
3
+
4
+ require 'rubygems'
5
+ require 'rubygems/user_interaction' if Gem::RubyGemsVersion == '1.5.0'
6
+
7
+ require 'rake'
8
+ require 'rake/clean'
9
+ require 'rake/task'
10
+
11
+
12
+ #
13
+ # clean
14
+
15
+ CLEAN.include('pkg', 'rdoc')
16
+
17
+
18
+ #
19
+ # test / spec
20
+
21
+ task :spec do
22
+
23
+ sh 'rspec spec/'
24
+ end
25
+
26
+ task :test => [ :spec ]
27
+ task :default => [ :spec ]
28
+
29
+
30
+ #
31
+ # gem
32
+
33
+ GEMSPEC_FILE = Dir['*.gemspec'].first
34
+ GEMSPEC = eval(File.read(GEMSPEC_FILE))
35
+ GEMSPEC.validate
36
+
37
+
38
+ desc %{
39
+ builds the gem and places it in pkg/
40
+ }
41
+ task :build do
42
+
43
+ sh "gem build #{GEMSPEC_FILE}"
44
+ sh "mkdir pkg" rescue nil
45
+ sh "mv #{GEMSPEC.name}-#{GEMSPEC.version}.gem pkg/"
46
+ end
47
+
48
+ desc %{
49
+ builds the gem and pushes it to rubygems.org
50
+ }
51
+ task :push => :build do
52
+
53
+ sh "gem push pkg/#{GEMSPEC.name}-#{GEMSPEC.version}.gem"
54
+ end
55
+
56
+
57
+ #
58
+ # rabbitmq preparation
59
+
60
+ desc %{
61
+ prepare RabbitMQ (vhost, user, perms)
62
+ }
63
+ task :prepare do
64
+
65
+ sh "rabbitmqctl add_vhost ruote-test"
66
+ sh "rabbitmqctl add_user ruote ruote"
67
+ sh "rabbitmqctl set_permissions -p ruote-test ruote '.*' '.*' '.*'"
68
+ end
69
+
70
+
71
+ #
72
+ # rdoc
73
+ #
74
+ # make sure to have rdoc 2.5.x to run that
75
+
76
+ # Rake::RDocTask.new do |rd|
77
+ #
78
+ # rd.main = 'README.rdoc'
79
+ # rd.rdoc_dir = 'rdoc'
80
+ #
81
+ # rd.rdoc_files.include(
82
+ # 'README.rdoc', 'CHANGELOG.txt', 'CREDITS.txt', 'lib/**/*.rb')
83
+ #
84
+ # rd.title = "#{GEMSPEC.name} #{GEMSPEC.version}"
85
+ # end
86
+
87
+
88
+ #
89
+ # upload_rdoc
90
+
91
+ # desc %{
92
+ # upload the rdoc to rubyforge
93
+ # }
94
+ # task :upload_rdoc => [ :clean, :rdoc ] do
95
+ #
96
+ # account = 'jmettraux@rubyforge.org'
97
+ # webdir = '/var/www/gforge-projects/ruote'
98
+ #
99
+ # sh "rsync -azv -e ssh rdoc/#{GEMSPEC.name}_rdoc #{account}:#{webdir}/"
100
+ # end
101
+
data/TODO.txt ADDED
@@ -0,0 +1,4 @@
1
+
2
+ [ ] have a class method ParticipantProxy.stop_all ?
3
+ [ ] use Ruote::Workitem #as_json and #from_json(s)
4
+
@@ -0,0 +1,22 @@
1
+
2
+ module RuoteStomp
3
+
4
+ #
5
+ # Got replaced by RuoteStomp::Receiver
6
+ #
7
+ # This class is kept for backward compatibility.
8
+ #
9
+ class LaunchitemListener < ::RuoteStomp::Receiver
10
+
11
+ # Start a new LaunchItem listener
12
+ #
13
+ # @param [ Ruote::Engine, Ruote::Storage ] A configured ruote engine or storage instance
14
+ # @param opts :queue / :unsubscribe
15
+ #
16
+ def initialize(engine_or_storage, opts={})
17
+
18
+ super(engine_or_storage, opts.merge(:launchitems => :only))
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,225 @@
1
+
2
+ require 'ruote/part/local_participant'
3
+ require 'ruote-stomp'
4
+
5
+
6
+ module RuoteStomp
7
+
8
+ #
9
+ # = Stomp Participants
10
+ #
11
+ # The RuoteStomp::ParticipantProxy allows you to send workitems (serialized as
12
+ # JSON) or messages to any Stomp queues right from the process
13
+ # definition. When combined with the RuoteStomp::Receiver you can easily
14
+ # leverage an extremely powerful local/remote participant
15
+ # combinations.
16
+ #
17
+ # For local/remote participants The local part of the
18
+ # RuoteStomp::ParticipantProxy relies on the presence of a
19
+ # RuoteStomp::Receiver. Workitems are sent to the remote participant
20
+ # and the local part does not normally reply to the engine. Instead
21
+ # the engine will continue when a reply is received on the
22
+ # 'ruote_workitems' queue (see RuoteStomp::Receiver).
23
+ #
24
+ # Of course, the standard :forget => true format can be used even
25
+ # with remote particpants and :forget can even be set as a default in
26
+ # the options.
27
+ #
28
+ # [NOTE: Working this port next!!!]
29
+ # A simple way to create a remote participant to act upon workitems
30
+ # is to use the daemon-kit ruote responder.
31
+ #
32
+ # Simple Stomp messages are treated as 'fire and forget' and the flow
33
+ # will continue when the local participant has queued the message
34
+ # for sending. (As there is no meaningful way to receive a workitem
35
+ # in reply).
36
+ #
37
+ # == Configuration
38
+ #
39
+ # Stomp configuration is handled by directly manipulating the
40
+ # values of the +Stomp.settings+ hash, as provided by the Stomp
41
+ # gem. No Stomp defaults are set by the participant.
42
+ #
43
+ # == Usage
44
+ #
45
+ # Define the queue used by an AMQP participant :
46
+ #
47
+ # engine.register_participant(
48
+ # :delete_user, RuoteStomp::ParticipantProxy, 'queue' => 'user_manager')
49
+ #
50
+ # Sending a workitem to the remote participant defined above:
51
+ #
52
+ # Ruote.process_definition do
53
+ # sequence do
54
+ # delete_user
55
+ # end
56
+ # end
57
+ #
58
+ # Let the local participant reply to the engine without involving
59
+ # the receiver
60
+ #
61
+ # Ruote.process_definition do
62
+ # sequence do
63
+ # delete_user :forget => true
64
+ # end
65
+ # end
66
+ #
67
+ # Setting up the participant in a slightly more 'raw' way:
68
+ #
69
+ # engine.register_participant(
70
+ # :stomp, RuoteStomp::ParticipantProxy )
71
+ #
72
+ # Sending a workitem to a specific queue:
73
+ #
74
+ # Ruote.process_definition do
75
+ # sequence do
76
+ # stomp :queue => 'test', 'command' => '/run/regression_test'
77
+ # end
78
+ # end
79
+ #
80
+ # Setup a 'fire and forget' participant that always replies to the
81
+ # engine:
82
+ #
83
+ # engine.register_participant(
84
+ # :jfdi, RuoteStomp::ParticipantProxy, 'forget' => true )
85
+ #
86
+ # Sending a message example to a specific queue (both steps are
87
+ # equivalent):
88
+ #
89
+ # Ruote.process_definition do
90
+ # sequence do
91
+ # stomp :queue => 'test', :message => 'foo'
92
+ # stomp :queue => 'test', :message => 'foo', :forget => true
93
+ # end
94
+ # end
95
+ #
96
+ #
97
+ # == Stomp notes
98
+ #
99
+ # The direct exchanges are always marked as durable by the
100
+ # participant, and messages are marked as persistent by default (see
101
+ # #RuoteStomp)
102
+ #
103
+ class ParticipantProxy
104
+
105
+ include Ruote::LocalParticipant
106
+
107
+ # The following parameters are used in the process definition.
108
+ #
109
+ # An options hash with the same keys to provide defaults is
110
+ # accepted at registration time (see above).
111
+ #
112
+ # * :queue => (string) The Stomp queue used by the remote participant.
113
+ # nil by default.
114
+ # * :forget => (bool) Whether the flow should block until the remote
115
+ # participant replies.
116
+ # false by default
117
+ #
118
+ def initialize(options)
119
+ @options = {
120
+ 'queue' => nil,
121
+ 'forget' => false,
122
+ }.merge(options.inject({}) { |h, (k, v)|
123
+ h[k.to_s] = v; h
124
+ })
125
+ #
126
+ # the inject is here to make sure that all options have String keys
127
+ end
128
+
129
+ # Process the workitem at hand. By default the workitem will be
130
+ # published to the direct exchange specified in the +queue+
131
+ # workitem parameter. You can specify a +message+ workitem
132
+ # parameter to have that sent instead of the workitem.
133
+ #
134
+ def consume(workitem)
135
+
136
+ RuoteStomp.start!
137
+ target_queue = determine_queue(workitem)
138
+
139
+ raise 'no queue specified (outbound delivery)' unless target_queue
140
+
141
+ #q = MQ.queue(target_queue, :durable => true)
142
+ forget = determine_forget(workitem)
143
+
144
+ opts = {
145
+ :persistent => RuoteStomp.use_persistent_messages?,
146
+ :content_type => 'application/json' }
147
+
148
+ if message = workitem.fields['message'] || workitem.params['message']
149
+
150
+ forget = true # sending a message implies 'forget' => true
151
+ $stomp.publish target_queue, message, opts
152
+ #q.publish(message, opts)
153
+
154
+ else
155
+ $stomp.publish target_queue, encode_workitem(workitem), opts
156
+ #q.publish(encode_workitem(workitem), opts)
157
+ end
158
+
159
+ reply_to_engine(workitem) if forget
160
+ end
161
+
162
+ # (Stops the underlying queue subscription)
163
+ #
164
+ def stop
165
+
166
+ RuoteStomp.stop!
167
+ end
168
+
169
+ def cancel(fei, flavour)
170
+ #
171
+ # TODO : sending a cancel item is not a bad idea, especially if the
172
+ # job done over the stomp fence lasts...
173
+ #
174
+ end
175
+
176
+ # [NOT sure about this behavior with Stomp yet. Need to dive.]
177
+
178
+ def do_not_thread
179
+
180
+ true
181
+ end
182
+
183
+ private
184
+
185
+ def determine_forget(workitem)
186
+
187
+ return workitem.params['forget'] if workitem.params.has_key?('forget')
188
+ return @options['forget'] if @options.has_key?('forget')
189
+ false
190
+ end
191
+
192
+ def determine_queue(workitem)
193
+
194
+ workitem.params['queue'] || @options['queue']
195
+ end
196
+
197
+ # Encodes the workitem as JSON. Makes sure to add to the field 'params'
198
+ # an entry named 'participant_options' which contains the options of
199
+ # this participant.
200
+ #
201
+ def encode_workitem(wi)
202
+
203
+ wi.params['participant_options'] = @options
204
+
205
+ Rufus::Json.encode(wi.to_h)
206
+ end
207
+ end
208
+
209
+ #
210
+ # Kept for backward compatibility.
211
+ #
212
+ # You should use RuoteStomp::ParticipantProxy.
213
+ #
214
+ class Participant < ParticipantProxy
215
+
216
+ def initialize(options)
217
+ puts '=' * 80
218
+ puts "RuoteStomp::Participant will be deprecated soon (2.1.12)"
219
+ puts "please use RuoteStomp::ParticipantProxy instead"
220
+ puts '=' * 80
221
+ super
222
+ end
223
+ end
224
+ end
225
+