ruote-stomp 2.2.0.a

Sign up to get free protection for your applications and to get access to all the features.
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
+