zmqmachine 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,195 @@
1
+
2
+ require 'rubygems'
3
+ require 'ffi-rzmq'
4
+ require '../lib/zmqmachine'
5
+
6
+
7
+ # Shows how to use a PUB socket to send messages in a fanout
8
+ # manner. A set of SUB sockets subscribe using different topic
9
+ # matches.
10
+ #
11
+ # The example also shows how to communicate between multiple
12
+ # reactors by running some operations in different contexts.
13
+ # Modify which lines are commented in/out within each context
14
+ # to see how performance changes in different scenarios.
15
+ #
16
+
17
+ class PublisherHandler
18
+ attr_reader :sent_count
19
+
20
+ def initialize context, port, topics
21
+ @context = context
22
+ @port = port
23
+ @topics = topics
24
+ @sent_count = 0
25
+ end
26
+
27
+ def on_attach socket
28
+ address = ZM::Address.new '127.0.0.1', @port, :tcp
29
+ rc = socket.bind address
30
+ end
31
+
32
+ def on_writable socket
33
+ topic = @topics[rand(@topics.size)]
34
+ symbol = topic.split('.').first
35
+
36
+ if 'es' == symbol
37
+ payload = "#{topic}|#{rand(1200) + 1}|#{rand(4400)}"
38
+ else
39
+ payload = "#{topic}|#{rand(300) + 1}|#{rand(8000)}"
40
+ end
41
+
42
+ message = ZMQ::Message.new payload
43
+ socket.send_message message
44
+ @sent_count += 1
45
+ end
46
+ end
47
+
48
+ class SubscriberHandler
49
+ attr_reader :received_count, :topics
50
+
51
+ def initialize context, ports, topic = nil, sleep = false
52
+ @context = context
53
+ @received_count = 0
54
+ @ports = ports
55
+ (@topics ||= []) << topic.to_s
56
+ @sleep = sleep
57
+ end
58
+
59
+ def on_attach socket
60
+ @ports.each do |port|
61
+ address = ZM::Address.new '127.0.0.1', port, :tcp
62
+ rc = socket.connect address
63
+
64
+ @topics.each do |topic|
65
+ puts "subscribe to [#{topic}]"
66
+ socket.subscribe topic
67
+ end
68
+ end
69
+ end
70
+
71
+ def on_readable socket, messages
72
+ @received_count += 1
73
+ sleep 0.01 if @sleep
74
+ end
75
+ end
76
+
77
+
78
+ # Mix and match the handlers amongst the 5 reactors below. Make sure that a publisher
79
+ # handler is only getting instantiated and run in one reactor at a time. The subscriber
80
+ # handlers can be instantiated multiple times in each reactor if you so choose.
81
+
82
+ # Run all handlers within the same reactor context
83
+ ctx1 = ZM::Reactor.new(:A).run do |context|
84
+ @pub1_handler = PublisherHandler.new context, 5555, ['futures.us.es.m.10', 'futures.us.es.u.10']
85
+ context.pub_socket @pub1_handler
86
+
87
+ # @pub2_handler = PublisherHandler.new context, 5556, ['futures.us.nq.m.10', 'futures.us.nq.u.10']
88
+ # context.pub_socket @pub2_handler
89
+ #
90
+ # @sub1_handler = SubscriberHandler.new context, [5555, 5556]
91
+ # context.sub_socket @sub1_handler
92
+ #
93
+ # @sub2_handler = SubscriberHandler.new context, [5555], 'futures.us.es.m'
94
+ # context.sub_socket @sub2_handler
95
+ #
96
+ # @sub3_handler = SubscriberHandler.new context, [5555], 'futures.us.es.u'
97
+ # context.sub_socket @sub3_handler
98
+ #
99
+ # @sub4_handler = SubscriberHandler.new context, [5556], 'futures.us.nq.m'
100
+ # context.sub_socket @sub4_handler
101
+ #
102
+ # @sub5_handler = SubscriberHandler.new context, [5555, 5556], 'futures.us.'
103
+ # context.sub_socket @sub5_handler
104
+ end
105
+
106
+ # Or, run each handler in separate contexts each with its
107
+ # own thread.
108
+ ctx2 = ZM::Reactor.new(:B).run do |context|
109
+ # @pub1_handler = PublisherHandler.new context, 5555, ['futures.us.es.m.10', 'futures.us.es.u.10']
110
+ # context.pub_socket @pub1_handler
111
+
112
+ @pub2_handler = PublisherHandler.new context, 5556, ['futures.us.nq.m.10', 'futures.us.nq.u.10']
113
+ context.pub_socket @pub2_handler
114
+
115
+ # @sub1_handler = SubscriberHandler.new context, [5555, 5556]
116
+ # context.sub_socket @sub1_handler
117
+ #
118
+ # @sub2_handler = SubscriberHandler.new context, [5555], 'futures.us.es.m'
119
+ # context.sub_socket @sub2_handler
120
+ #
121
+ # @sub3_handler = SubscriberHandler.new context, [5555], 'futures.us.es.u'
122
+ # context.sub_socket @sub3_handler
123
+ #
124
+ # @sub4_handler = SubscriberHandler.new context, [5556], 'futures.us.nq.m'
125
+ # context.sub_socket @sub4_handler
126
+ #
127
+ # @sub5_handler = SubscriberHandler.new context, [5555, 5556], 'futures.us.'
128
+ # context.sub_socket @sub5_handler
129
+ end
130
+
131
+ ctx3 = ZM::Reactor.new(:C).run do |context|
132
+ # @pub1_handler = PublisherHandler.new context, 5555, ['futures.us.es.m.10', 'futures.us.es.u.10']
133
+ # context.pub_socket @pub1_handler
134
+ #
135
+ # @pub2_handler = PublisherHandler.new context, 5556, ['futures.us.nq.m.10', 'futures.us.nq.u.10']
136
+ # context.pub_socket @pub2_handler
137
+ #
138
+ @sub1_handler = SubscriberHandler.new context, [5555, 5556]
139
+ context.sub_socket @sub1_handler
140
+
141
+ @sub2_handler = SubscriberHandler.new context, [5555], 'futures.us.es.m'
142
+ context.sub_socket @sub2_handler
143
+
144
+ @sub3_handler = SubscriberHandler.new context, [5555], 'futures.us.es.u'
145
+ context.sub_socket @sub3_handler
146
+
147
+ @sub4_handler = SubscriberHandler.new context, [5556], 'futures.us.nq.m'
148
+ context.sub_socket @sub4_handler
149
+
150
+ # @sub5_handler = SubscriberHandler.new context, [5555, 5556], 'futures.us.'
151
+ # context.sub_socket @sub5_handler
152
+ end
153
+
154
+ ctx4 = ZM::Reactor.new(:D).run do |context|
155
+ # @pub1_handler = PublisherHandler.new context, 5555, ['futures.us.es.m.10', 'futures.us.es.u.10']
156
+ # context.pub_socket @pub1_handler
157
+ #
158
+ # @pub2_handler = PublisherHandler.new context, 5556, ['futures.us.nq.m.10', 'futures.us.nq.u.10']
159
+ # context.pub_socket @pub2_handler
160
+ #
161
+ # @sub1_handler = SubscriberHandler.new context, [5555, 5556]
162
+ # context.sub_socket @sub1_handler
163
+ #
164
+ # @sub2_handler = SubscriberHandler.new context, [5555], 'futures.us.es.m'
165
+ # context.sub_socket @sub2_handler
166
+ #
167
+ # @sub3_handler = SubscriberHandler.new context, [5555], 'futures.us.es.u'
168
+ # context.sub_socket @sub3_handler
169
+ #
170
+ # @sub4_handler = SubscriberHandler.new context, [5556], 'futures.us.nq.m'
171
+ # context.sub_socket @sub4_handler
172
+
173
+ @sub5_handler = SubscriberHandler.new context, [5555, 5556], 'futures.us.'
174
+ context.sub_socket @sub5_handler
175
+ end
176
+
177
+ # let's see how many messages we can publish in this many seconds
178
+ sleep_time = 5
179
+ puts "Started at [#{Time.now}]"
180
+ puts "main thread will sleep [#{sleep_time}] seconds before aborting the reactor context threads"
181
+ sleep sleep_time
182
+
183
+ # Exit each reactor after the sleep time
184
+ ctx1.stop
185
+ ctx2.stop
186
+ ctx3.stop
187
+ ctx4.stop
188
+
189
+ puts "sent [#{@pub1_handler.sent_count}]"
190
+ puts "sent [#{@pub2_handler.sent_count}]"
191
+ puts "* [#{@sub1_handler.received_count}]"
192
+ puts "futures.us.ep.m [#{@sub2_handler.received_count}]"
193
+ puts "futures.us.ep.u [#{@sub3_handler.received_count}]"
194
+ puts "futures.us.nq.m [#{@sub4_handler.received_count}]"
195
+ puts "futures.us.nq [#{@sub5_handler.received_count}]"
@@ -0,0 +1,103 @@
1
+
2
+ require 'rubygems'
3
+ require 'ffi-rzmq'
4
+ require '../lib/zmqmachine'
5
+
6
+ # This example illustrates how to write a simple set of
7
+ # handlers for providing message ping-pong using
8
+ # a PAIR socket pair. All activity is asynchronous and
9
+ # relies on non-blocking I/O.
10
+ #
11
+ # The throttling aspect doesn't really kick in; need to
12
+ # ask the 0mq guys for clarity.
13
+
14
+ class PongHandler
15
+ attr_reader :sent_count, :received_count
16
+
17
+ def initialize context
18
+ @context = context
19
+ @sent_count = 0
20
+ @received_count = 0
21
+ end
22
+
23
+ def on_attach socket
24
+ address = ZM::Address.new '127.0.0.1', 5555, :tcp
25
+ rc = socket.bind address
26
+ end
27
+
28
+ def on_readable socket, messages
29
+ @received_count += 1
30
+ pong socket, messages.first
31
+ end
32
+
33
+ def on_writable socket
34
+ #puts "pong on_writable"
35
+ end
36
+
37
+ def pong socket, message
38
+ socket.send_message message
39
+ @sent_count += 1
40
+ end
41
+ end
42
+
43
+ class PingHandler
44
+ attr_reader :sent_count, :received_count
45
+
46
+ def initialize context
47
+ @context = context
48
+ @sent_count = 0
49
+ @received_count = 0
50
+ end
51
+
52
+ def on_attach socket
53
+ address = ZM::Address.new '127.0.0.1', 5555, :tcp
54
+ rc = socket.connect address
55
+ end
56
+
57
+ def on_readable socket, messages
58
+ @received_count += 1
59
+ end
60
+
61
+ def on_writable socket
62
+ #puts "ping on_writable"
63
+ ping socket
64
+ end
65
+
66
+ # send as fast as possible until we hit our high water
67
+ # mark and get EAGAIN; then break
68
+ def ping socket
69
+ message = ZMQ::Message.new "#{'b' * 2048}"
70
+ rc = socket.send_message message
71
+ @sent_count += 1
72
+ end
73
+ end
74
+
75
+
76
+
77
+ # Run both handlers within the same reactor context
78
+ ctx1 = ZM::Reactor.new(:pong).run do |context|
79
+ @pong_handler = PongHandler.new context
80
+ context.pair_socket @pong_handler
81
+
82
+ # If you uncomment these 2 lines, comment out the
83
+ # +ctx2+ block below.
84
+ # @ping_handler = PingHandler.new context
85
+ # context.pair_socket @ping_handler
86
+ end
87
+
88
+ # Or, run each handler in separate contexts each with its
89
+ # own thread.
90
+ ctx2 = ZM::Reactor.new(:ping).run do |context|
91
+ @ping_handler = PingHandler.new context
92
+ context.pair_socket @ping_handler
93
+ end
94
+
95
+ # let's see how many messages we can transfer in this many seconds
96
+ sleep_time = 5
97
+ puts "Started at [#{Time.now}]"
98
+ puts "main thread will sleep [#{sleep_time}] seconds before aborting the context threads"
99
+ sleep sleep_time
100
+
101
+ ctx1.stop
102
+ ctx2.stop
103
+ puts "received [#{@pong_handler.received_count}], sent [#{@ping_handler.sent_count}]"
data/lib/zm/address.rb ADDED
@@ -0,0 +1,70 @@
1
+ #--
2
+ #
3
+ # Author:: Chuck Remes
4
+ # Homepage:: http://github.com/chuckremes/zmqmachine
5
+ # Date:: 20100602
6
+ #
7
+ #----------------------------------------------------------------------------
8
+ #
9
+ # Copyright (C) 2010 by Chuck Remes. All Rights Reserved.
10
+ # Email: cremes at mac dot com
11
+ #
12
+ # (The MIT License)
13
+ #
14
+ # Permission is hereby granted, free of charge, to any person obtaining
15
+ # a copy of this software and associated documentation files (the
16
+ # 'Software'), to deal in the Software without restriction, including
17
+ # without limitation the rights to use, copy, modify, merge, publish,
18
+ # distribute, sublicense, and/or sell copies of the Software, and to
19
+ # permit persons to whom the Software is furnished to do so, subject to
20
+ # the following conditions:
21
+ #
22
+ # The above copyright notice and this permission notice shall be
23
+ # included in all copies or substantial portions of the Software.
24
+ #
25
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
26
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
29
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
30
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
31
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
+ #
33
+ #---------------------------------------------------------------------------
34
+ #
35
+ #
36
+
37
+ module ZMQMachine
38
+
39
+ #FIXME: needs to handle ipc and inproc transports better, e.g.
40
+ # there is no port component to either one.
41
+ #
42
+ class Address
43
+ attr_reader :host, :port, :transport
44
+
45
+ # +type+ : :tcp, :pgm or :inprocess
46
+ def initialize host, port, type = :tcp
47
+ @host = host
48
+ @port = port
49
+ @transport = determine_type type
50
+ end
51
+
52
+ def to_s
53
+ "#{@transport}://#{@host}:#{@port}"
54
+ end
55
+
56
+ private
57
+
58
+ def determine_type type
59
+ case type
60
+ when :inprocess
61
+ :inproc
62
+ when :tcp, :pgm
63
+ type
64
+ else
65
+ raise UnknownAddressError, "Unknown address transport type [#{type}]; must be :tcp, :pgm, or :inprocess"
66
+ end
67
+ end
68
+
69
+ end # class Address
70
+ end # module ZMQMachine
@@ -0,0 +1,209 @@
1
+ #--
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 16 Jul 2006
6
+ #
7
+ # See EventMachine and EventMachine::Connection for documentation and
8
+ # usage examples.
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13
+ # Gmail: blackhedd
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ #---------------------------------------------------------------------------
21
+ #
22
+ #
23
+
24
+ module ZMQMachine
25
+
26
+ module Deferrable
27
+
28
+ # Specify a block to be executed if and when the Deferrable object receives
29
+ # a status of :succeeded. See #set_deferred_status for more information.
30
+ #
31
+ # Calling this method on a Deferrable object whose status is not yet known
32
+ # will cause the callback block to be stored on an internal list.
33
+ # If you call this method on a Deferrable whose status is :succeeded, the
34
+ # block will be executed immediately, receiving the parameters given to the
35
+ # prior #set_deferred_status call.
36
+ #
37
+ #--
38
+ # If there is no status, add a callback to an internal list.
39
+ # If status is succeeded, execute the callback immediately.
40
+ # If status is failed, do nothing.
41
+ #
42
+ def callback &block
43
+ return unless block
44
+ @deferred_status ||= :unknown
45
+ if @deferred_status == :succeeded
46
+ block.call(*@deferred_args)
47
+ elsif @deferred_status != :failed
48
+ @callbacks ||= []
49
+ @callbacks.unshift block
50
+ end
51
+ end
52
+
53
+ # Cancels an outstanding callback to &block if any. Undoes the action of #callback.
54
+ #
55
+ def cancel_callback block
56
+ @callbacks ||= []
57
+ @callbacks.delete block
58
+ end
59
+
60
+ # Specify a block to be executed if and when the Deferrable object receives
61
+ # a status of :failed. See #set_deferred_status for more information.
62
+ #--
63
+ # If there is no status, add an errback to an internal list.
64
+ # If status is failed, execute the errback immediately.
65
+ # If status is succeeded, do nothing.
66
+ #
67
+ def errback &block
68
+ return unless block
69
+ @deferred_status ||= :unknown
70
+ if @deferred_status == :failed
71
+ block.call(*@deferred_args)
72
+ elsif @deferred_status != :succeeded
73
+ @errbacks ||= []
74
+ @errbacks.unshift block # << block
75
+ end
76
+ end
77
+
78
+ # Cancels an outstanding errback to &block if any. Undoes the action of #errback.
79
+ #
80
+ def cancel_errback block
81
+ @errbacks ||= []
82
+ @errbacks.delete block
83
+ end
84
+
85
+ # Sets the "disposition" (status) of the Deferrable object. See also the large set of
86
+ # sugarings for this method.
87
+ # Note that if you call this method without arguments,
88
+ # no arguments will be passed to the callback/errback.
89
+ # If the user has coded these with arguments, then the
90
+ # user code will throw an argument exception.
91
+ # Implementors of deferrable classes <b>must</b>
92
+ # document the arguments they will supply to user callbacks.
93
+ #
94
+ # OBSERVE SOMETHING VERY SPECIAL here: you may call this method even
95
+ # on the INSIDE of a callback. This is very useful when a previously-registered
96
+ # callback wants to change the parameters that will be passed to subsequently-registered
97
+ # ones.
98
+ #
99
+ # You may give either :succeeded or :failed as the status argument.
100
+ #
101
+ # If you pass :succeeded, then all of the blocks passed to the object using the #callback
102
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
103
+ # passed to the object using #errback will be discarded.
104
+ #
105
+ # If you pass :failed, then all of the blocks passed to the object using the #errback
106
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
107
+ # passed to the object using # callback will be discarded.
108
+ #
109
+ # If you pass any arguments to #set_deferred_status in addition to the status argument,
110
+ # they will be passed as arguments to any callbacks or errbacks that are executed.
111
+ # It's your responsibility to ensure that the argument lists specified in your callbacks and
112
+ # errbacks match the arguments given in calls to #set_deferred_status, otherwise Ruby will raise
113
+ # an ArgumentError.
114
+ #
115
+ #--
116
+ # We're shifting callbacks off and discarding them as we execute them.
117
+ # This is valid because by definition callbacks are executed no more than
118
+ # once. It also has the magic effect of permitting recursive calls, which
119
+ # means that a callback can call #set_deferred_status and change the parameters
120
+ # that will be sent to subsequent callbacks down the chain.
121
+ #
122
+ # Changed @callbacks and @errbacks from push/shift to unshift/pop, per suggestion
123
+ # by Kirk Haines, to work around the memory leak bug that still exists in many Ruby
124
+ # versions.
125
+ #
126
+ # Changed 15Sep07: after processing callbacks or errbacks, CLEAR the other set of
127
+ # handlers. This gets us a little closer to the behavior of Twisted's "deferred,"
128
+ # which only allows status to be set once. Prior to making this change, it was possible
129
+ # to "succeed" a Deferrable (triggering its callbacks), and then immediately "fail" it,
130
+ # triggering its errbacks! That is clearly undesirable, but it's just as undesirable
131
+ # to raise an exception is status is set more than once on a Deferrable. The latter
132
+ # behavior would invalidate the idiom of resetting arguments by setting status from
133
+ # within a callback or errback, but more seriously it would cause spurious errors
134
+ # if a Deferrable was timed out and then an attempt was made to succeed it. See the
135
+ # comments under the new method #timeout.
136
+ #
137
+ def set_deferred_status status, *args
138
+ cancel_timeout
139
+ @errbacks ||= nil
140
+ @callbacks ||= nil
141
+ @deferred_status = status
142
+ @deferred_args = args
143
+ case @deferred_status
144
+ when :succeeded
145
+ if @callbacks
146
+ while cb = @callbacks.pop
147
+ cb.call(*@deferred_args)
148
+ end
149
+ end
150
+ @errbacks.clear if @errbacks
151
+ when :failed
152
+ if @errbacks
153
+ while eb = @errbacks.pop
154
+ eb.call(*@deferred_args)
155
+ end
156
+ end
157
+ @callbacks.clear if @callbacks
158
+ end
159
+ end
160
+
161
+
162
+ # Setting a timeout on a Deferrable causes it to go into the failed state after
163
+ # the Timeout expires (passing no arguments to the object's errbacks).
164
+ # Setting the status at any time prior to a call to the expiration of the timeout
165
+ # will cause the timer to be cancelled.
166
+ def timeout seconds, *args
167
+ cancel_timeout
168
+ me = self
169
+
170
+ # we use milliseconds, not seconds, so adjust the passed in time
171
+ seconds *= 1000
172
+ @deferred_timeout = ZMQMachine::Timers.add_oneshot seconds {me.fail(*args)}
173
+ end
174
+
175
+ # Cancels an outstanding timeout if any. Undoes the action of #timeout.
176
+ #
177
+ def cancel_timeout
178
+ @deferred_timeout ||= nil
179
+ if @deferred_timeout
180
+ @deferred_timeout.cancel
181
+ @deferred_timeout = nil
182
+ end
183
+ end
184
+
185
+
186
+ # Sugar for set_deferred_status(:succeeded, ...)
187
+ #
188
+ def succeed *args
189
+ set_deferred_status :succeeded, *args
190
+ end
191
+ alias set_deferred_success succeed
192
+
193
+ # Sugar for set_deferred_status(:failed, ...)
194
+ #
195
+ def fail *args
196
+ set_deferred_status :failed, *args
197
+ end
198
+ alias set_deferred_failure fail
199
+ end
200
+
201
+
202
+ # DefaultDeferrable is an otherwise empty class that includes Deferrable.
203
+ # This is very useful when you just need to return a Deferrable object
204
+ # as a way of communicating deferred status to some other part of a program.
205
+ class DefaultDeferrable
206
+ include Deferrable
207
+ end
208
+
209
+ end # module ZMQMachine
@@ -0,0 +1,45 @@
1
+ #--
2
+ #
3
+ # Author:: Chuck Remes
4
+ # Homepage:: http://github.com/chuckremes/zmqmachine
5
+ # Date:: 20100602
6
+ #
7
+ #----------------------------------------------------------------------------
8
+ #
9
+ # Copyright (C) 2010 by Chuck Remes. All Rights Reserved.
10
+ # Email: cremes at mac dot com
11
+ #
12
+ # (The MIT License)
13
+ #
14
+ # Permission is hereby granted, free of charge, to any person obtaining
15
+ # a copy of this software and associated documentation files (the
16
+ # 'Software'), to deal in the Software without restriction, including
17
+ # without limitation the rights to use, copy, modify, merge, publish,
18
+ # distribute, sublicense, and/or sell copies of the Software, and to
19
+ # permit persons to whom the Software is furnished to do so, subject to
20
+ # the following conditions:
21
+ #
22
+ # The above copyright notice and this permission notice shall be
23
+ # included in all copies or substantial portions of the Software.
24
+ #
25
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
26
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
29
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
30
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
31
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
+ #
33
+ #---------------------------------------------------------------------------
34
+ #
35
+ #
36
+
37
+ module ZMQMachine
38
+
39
+ class TimeoutError < StandardError; end
40
+
41
+ class UnknownAddressError < StandardError; end
42
+
43
+ class NotReadyError < StandardError; end
44
+
45
+ end # module ZMQMachine
data/lib/zm/message.rb ADDED
@@ -0,0 +1,52 @@
1
+ #--
2
+ #
3
+ # Author:: Chuck Remes
4
+ # Homepage:: http://github.com/chuckremes/zmqmachine
5
+ # Date:: 20100602
6
+ #
7
+ #----------------------------------------------------------------------------
8
+ #
9
+ # Copyright (C) 2010 by Chuck Remes. All Rights Reserved.
10
+ # Email: cremes at mac dot com
11
+ #
12
+ # (The MIT License)
13
+ #
14
+ # Permission is hereby granted, free of charge, to any person obtaining
15
+ # a copy of this software and associated documentation files (the
16
+ # 'Software'), to deal in the Software without restriction, including
17
+ # without limitation the rights to use, copy, modify, merge, publish,
18
+ # distribute, sublicense, and/or sell copies of the Software, and to
19
+ # permit persons to whom the Software is furnished to do so, subject to
20
+ # the following conditions:
21
+ #
22
+ # The above copyright notice and this permission notice shall be
23
+ # included in all copies or substantial portions of the Software.
24
+ #
25
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
26
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
29
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
30
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
31
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
+ #
33
+ #---------------------------------------------------------------------------
34
+ #
35
+ #
36
+
37
+ module ZMQMachine
38
+
39
+ module Message
40
+
41
+ # A unique identifier for this message
42
+ def identity
43
+
44
+ end
45
+
46
+ def encode
47
+ raise NotImplementedError, "You must implement the #encode method in your Message class", caller
48
+ # FIXME: default to json encoding?
49
+ end
50
+
51
+ end # module Message
52
+ end # module ZMQMachine