zactor 0.0.7 → 0.0.8

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/Gemfile CHANGED
@@ -9,7 +9,7 @@ group :development do
9
9
  gem "rr"
10
10
  gem "guard-rspec"
11
11
  gem "growl"
12
- gem "ruby-debug19"
12
+ gem "ruby-debug19", :platform => :mri_19
13
13
  gem "em-spec", :git => "https://github.com/mloughran/em-spec.git", :branch => 'rspec2'
14
14
  end
15
15
 
@@ -8,7 +8,7 @@ GIT
8
8
  PATH
9
9
  remote: .
10
10
  specs:
11
- zactor (0.0.7)
11
+ zactor (0.0.8)
12
12
  activesupport (> 0.1)
13
13
  bson (> 0.1)
14
14
  bson_ext (> 0.1)
@@ -16,6 +16,7 @@ PATH
16
16
  ffi (> 0.1)
17
17
  ffi-rzmq (> 0.1)
18
18
  ruby-interface (> 0)
19
+ uuid (> 0.1)
19
20
 
20
21
  GEM
21
22
  remote: http://rubygems.org/
@@ -23,8 +24,8 @@ GEM
23
24
  activesupport (3.0.7)
24
25
  archive-tar-minitar (0.5.2)
25
26
  bluecloth (2.1.0)
26
- bson (1.3.0)
27
- bson_ext (1.3.0)
27
+ bson (1.3.1)
28
+ bson_ext (1.3.1)
28
29
  columnize (0.3.2)
29
30
  configuration (1.2.0)
30
31
  diff-lcs (1.1.2)
@@ -32,8 +33,7 @@ GEM
32
33
  eventmachine (>= 1.0.0.beta.3)
33
34
  ffi-rzmq (>= 0.7.2)
34
35
  eventmachine (1.0.0.beta.3)
35
- ffi (1.0.7)
36
- rake (>= 0.8.7)
36
+ ffi (1.0.9)
37
37
  ffi-rzmq (0.8.0)
38
38
  growl (1.0.3)
39
39
  guard (0.3.0)
@@ -47,6 +47,7 @@ GEM
47
47
  rake (>= 0.8.1)
48
48
  linecache19 (0.5.11)
49
49
  ruby_core_source (>= 0.1.4)
50
+ macaddr (1.0.0)
50
51
  open_gem (1.4.2)
51
52
  launchy (~> 0.3.5)
52
53
  rake (0.8.7)
@@ -74,6 +75,8 @@ GEM
74
75
  ruby_core_source (0.1.4)
75
76
  archive-tar-minitar (>= 0.5.2)
76
77
  thor (0.14.6)
78
+ uuid (2.3.2)
79
+ macaddr (~> 1.0)
77
80
  yard (0.6.5)
78
81
 
79
82
  PLATFORMS
data/README.md CHANGED
@@ -6,43 +6,52 @@ Zactor использует zmq как бекенд для сообщений, e
6
6
 
7
7
  Каждый zactor-объект имеет свой identity, который генерируется автоматически, либо задается вручную и постоянен. Совокупность identity, host и port на которых был рожден этот объект, это достаточная информация для того что бы отправить этому объекту сообщение из другого объекта. Выглядит примерно так:
8
8
 
9
- zactor.actor =>
10
- {"identity"=>"actor.2154247120-0.0.0.0:8000", "host"=>"0.0.0.0:8000"}
11
-
12
- Ипользование
9
+ ```ruby
10
+ zactor.actor => {"identity"=>"actor.2154247120-0.0.0.0:8000", "host"=>"0.0.0.0:8000"}
11
+ ```
12
+
13
+ Использование
13
14
  ============
14
15
 
15
16
  Для начала нужно стартануть Zactor.
16
-
17
+
18
+ ```ruby
17
19
  Zactor.start 8000
18
-
20
+ ```
21
+
19
22
  Процесс забиндится на 0.0.0.0:8000, через эту точку будет происходить общение между zactor-процессами. Стартоваться должен в запущенном EM-контексте.
20
23
 
21
24
  В каждый zactor-активный класс нужно делать include Zactor, после чего у класса и его экземпляров для доступа к функциями Zactor появится метод zactor. После создания объекта нужно выполнить zactor.init
22
25
 
26
+ ```ruby
23
27
  class A
24
28
  include Zactor
25
-
29
+
26
30
  def initialize
27
31
  zactor.init
28
32
  end
29
33
  end
30
-
34
+ ```
35
+
31
36
  Для отправки сообщений другому объекту нам нужно знать его идентификатор. Идентификатор можно получить тремя способами:
32
37
 
33
- * Непосрдественной передачей. При инициализации или в любом другом месте, это исключительно внутренняя логика приложения. Идентификатор объекта можно получить вызвав zactor.actor
38
+ * Непосредственной передачей. При инициализации или в любом другом месте, это исключительно внутренняя логика приложения. Идентификатор объекта можно получить вызвав zactor.actor
34
39
  * При получении сообщения. В сообщении всегда содержится информация об отправителе
35
40
  * Если объект имеет заранее известный identity, то мы можем получить его полный идентификатор вызвав Zactor.get_actor с identity и хостом, на котором он запущен
36
-
41
+
42
+ ```ruby
37
43
  actor = Zactor.get_actor "broker", :host => "0.0.0.0:8001"
38
-
39
- Получив идентификатор можно отправлять ему сообщения
40
-
44
+ ```
45
+
46
+ Получив идентификатор, можно отправлять ему сообщения
47
+
48
+ ```ruby
41
49
  zactor.send_request actor, :show_me, :boobs
50
+ ```
42
51
 
43
-
44
- Каждый класс может определять какие именно ивенты он может получать и что с ними делать
45
-
52
+ Каждый класс может определять, какие именно события он может получать и что с ними делать
53
+
54
+ ```ruby
46
55
  include Zactor
47
56
 
48
57
  zactor do
@@ -55,9 +64,11 @@ Zactor использует zmq как бекенд для сообщений, e
55
64
  end
56
65
  end
57
66
  end
58
-
67
+ ```
68
+
59
69
  Рассмотрим пример банального ping-pong
60
70
 
71
+ ```ruby
61
72
  class A
62
73
  include Zactor
63
74
 
@@ -65,7 +76,7 @@ Zactor использует zmq как бекенд для сообщений, e
65
76
  zactor.init
66
77
  ping Zactor.get_actor("b")
67
78
  end
68
-
79
+
69
80
  def ping(actor)
70
81
  puts "Ping!"
71
82
  zactor.send_request actor, :ping do |res|
@@ -74,10 +85,9 @@ Zactor использует zmq как бекенд для сообщений, e
74
85
  end
75
86
  end
76
87
 
77
-
78
88
  class B
79
89
  include Zactor
80
-
90
+
81
91
  zactor do
82
92
  identity "b"
83
93
 
@@ -98,10 +108,11 @@ Zactor использует zmq как бекенд для сообщений, e
98
108
  a = A.new
99
109
  b = B.new
100
110
  end
101
-
111
+ ```
112
+
102
113
  A посылает сообщение :ping для B, а B отвечает "Pong!"
103
114
 
104
- В коллбэк определенный в event передается объект получившый сообщение, объект сообщения ({Zactor::Message}) и далее переданные в запросе аргументы (если они есть). У {Zactor::Message} есть два основных метода: sender, возвращающий идентификатор отправителя и reply, который посылает ответ на запрос.
115
+ В коллбэк, определенный в event, передается объект, получивший сообщение, объект сообщения ({Zactor::Message}) и далее переданные в запросе аргументы (если они есть). У {Zactor::Message} есть два основных метода: sender, возвращающий идентификатор отправителя и reply, который посылает ответ на запрос.
105
116
 
106
117
  Важный момент, identity должно задаваться ДО zactor.init и после этого не может меняться.
107
118
 
@@ -12,14 +12,21 @@ class A
12
12
  include Zactor
13
13
 
14
14
  def initialize
15
+ @counter = 0
15
16
  zactor.init
16
- ping Zactor.get_actor("b")
17
+ end
18
+
19
+ def start
20
+ ping Zactor.get_actor("b", :host => "0.0.0.0:#{ARGV[1]}")
17
21
  end
18
22
 
19
- def ping(actor)
20
- puts "Ping!"
23
+ def ping(actor)
21
24
  zactor.send_request actor, :ping do |res|
22
- puts res
25
+ @counter += 1
26
+ if @counter % 1000 == 0
27
+ puts @counter
28
+ end
29
+ EM.next_tick { ping(actor) }
23
30
  end
24
31
  end
25
32
  end
@@ -43,8 +50,10 @@ class B
43
50
  end
44
51
 
45
52
  EM.run do
46
- Zactor.start 8000
53
+
54
+ Zactor.start ARGV[0]
47
55
 
48
56
  a = A.new
49
57
  b = B.new
58
+ a.start
50
59
  end
@@ -4,12 +4,11 @@ require 'active_support/all'
4
4
  require 'ffi-rzmq'
5
5
  require 'em-zeromq'
6
6
  require 'bson'
7
-
7
+ require 'uuid'
8
8
  module Zactor
9
9
  extend ActiveSupport::Autoload
10
-
10
+ LinkTimeout = LinkInterval = 20
11
11
  autoload :Broker
12
- autoload :ActorSub
13
12
  autoload :ActorPub
14
13
  autoload :Message
15
14
  require 'zactor/log_subscriber'
@@ -17,19 +16,8 @@ module Zactor
17
16
  mattr_accessor :stub
18
17
  mattr_accessor :zmq, :logger
19
18
 
20
- class << self
21
- def broker
22
- @broker
23
- end
24
-
25
- def broker_port
26
- @broker_port
27
- end
28
-
29
- def host
30
- @host
31
- end
32
-
19
+ class << self
20
+ attr_accessor :broker, :broker_port, :host, :zactors
33
21
  def start(broker_port, params = {})
34
22
  self.zmq ||= EM::ZeroMQ::Context.new(1)
35
23
  self.logger ||= Logger.new(STDOUT).tap { |o| o.level = params[:debug] ? Logger::DEBUG : Logger::INFO }
@@ -39,6 +27,7 @@ module Zactor
39
27
 
40
28
  logger.info "Starting Zactor"
41
29
  @broker = Broker.new :balancer => params[:balancer]
30
+ @pubs = {}
42
31
  end
43
32
 
44
33
  def get_actor(pid, options = {})
@@ -48,18 +37,24 @@ module Zactor
48
37
 
49
38
  def register(zactor)
50
39
  @zactors ||= {}
51
- @zactors[zactor] = true
40
+ @zactors[zactor.identity] = zactor
52
41
  end
53
42
 
54
43
  def deregister(zactor)
55
- @zactors.delete zactor
44
+ @zactors ||= {}
45
+ @zactors.delete zactor.identity
56
46
  end
57
47
 
58
48
  def finish
59
- @zactors.keys.each(&:finish)
49
+ @zactors.values.each(&:finish)
50
+ @pubs.values.each(&:close)
60
51
  @broker.finish
61
52
  end
62
53
 
54
+ def pub(actor)
55
+ @pubs[actor['host']] ||= Zactor::ActorPub.new("tcp://#{actor['host']}")
56
+ end
57
+
63
58
  def clear
64
59
  @zactors = {}
65
60
  end
@@ -131,17 +126,13 @@ module Zactor
131
126
  end
132
127
  end
133
128
  attr_accessor :actor, :identity
134
- attr_accessor :pubs
135
129
 
136
130
  # Инициализация, подписывается на сообщения для себя, создает сокет для отправки локальных сообщений
137
131
  def init
138
- @actor = Zactor.get_actor @identity || self.class.identity_val || "actor.#{owner.object_id}-#{Zactor.host}"
132
+ @actor = Zactor.get_actor identity
139
133
  Zactor.register self
140
134
  return if Zactor.stub
141
- @sub = make_sub
142
135
  @callbacks, @timeouts = {}, {}
143
- @pubs = {}
144
- @pubs["0.0.0.0:#{Zactor.broker_port}"] = make_pub "inproc://zactor_broker_sub"
145
136
  end
146
137
 
147
138
  # Закрываем все соедниения и чистим сисьему. Обязательно нужно делать, когда объект перестает существовать
@@ -154,40 +145,62 @@ module Zactor
154
145
  end
155
146
  end
156
147
  @finished = true
157
- @sub.close
158
- @pubs.values.each(&:close)
159
148
  end
160
149
 
161
- def make_pub(endpoint)
162
- Zactor::ActorPub.new self, endpoint
163
- end
164
-
165
- def make_sub
166
- Zactor::ActorSub.new self
150
+ def identity
151
+ @identity ||= self.class.identity_val || "actor.#{UUID.generate}-#{Zactor.host}"
167
152
  end
168
153
 
169
154
  def send_request(actor, event, *args, &clb)
170
155
  return if @finished || Zactor.stub
171
156
  @callbacks[clb.object_id.to_s] = clb if clb
157
+ @last_callback = clb ? clb.object_id.to_s : ''
158
+ if actor['host'] == @actor['host']
159
+ internal_request actor, event, @last_callback, *args
160
+ else
161
+ extertanl_request actor, event, @last_callback, *args
162
+ end
163
+ self
164
+ end
165
+
166
+ def internal_request(actor, event, clb_id, *args)
167
+ receiver = Zactor.zactors[actor['identity']]
168
+ return unless receiver
169
+ receiver.receive_request @actor, event, clb_id, *args
170
+ end
171
+
172
+ def extertanl_request(actor, event, clb_id, *args)
172
173
  send_to actor, messages { |m|
173
174
  m.str 'request'
174
- m.str "#{clb ? clb.object_id : ''}"
175
+ m.str clb_id
175
176
  m.str event
176
177
  m.str BSON.serialize({ 'args' => args })
177
178
  }
178
- @last_callback = clb.object_id.to_s
179
- self
180
179
  end
181
180
 
182
181
  def timeout(secs, &clb)
183
182
  raise "Only for requests" unless @last_callback
183
+ return unless @callbacks[@last_callback] # в случае если коллбэк уже был выполнен синхронно
184
184
  last_clb = @last_callback
185
185
  @timeouts[last_clb] = EM.add_timer(secs) { @timeouts.delete(last_clb); clb.call }
186
186
  end
187
187
 
188
188
  def send_reply(actor, callback_id, *args)
189
189
  return if @finished || Zactor.stub
190
- Zactor.logger.debug "Zactor: send reply"
190
+ if actor['host'] == @actor['host']
191
+ internal_reply actor, callback_id, *args
192
+ else
193
+ external_reply actor, callback_id, *args
194
+ end
195
+ end
196
+
197
+ def internal_reply(actor, callback_id, *args)
198
+ receiver = Zactor.zactors[actor['identity']]
199
+ return unless receiver
200
+ receiver.receive_reply callback_id, *args
201
+ end
202
+
203
+ def external_reply(actor, callback_id, *args)
191
204
  send_to actor, messages { |m|
192
205
  m.str 'reply'
193
206
  m.str callback_id
@@ -196,7 +209,7 @@ module Zactor
196
209
  end
197
210
 
198
211
  def send_to(actor, mes = [])
199
- pub = @pubs[actor['host']] ||= make_pub("tcp://#{actor['host']}")
212
+ pub = Zactor.pub actor
200
213
  pub.send_messages(messages { |m|
201
214
  m.str actor['identity']
202
215
  m.str bson_actor
@@ -216,11 +229,11 @@ module Zactor
216
229
  end
217
230
 
218
231
  def link_ping(link_timer, actor, &clb)
219
- link_timer[:timer] = EM.add_timer(5) do
232
+ link_timer[:timer] = EM.add_timer(LinkInterval) do
220
233
  unless @finished
221
234
  send_request(actor, :link_ping) do
222
235
  link_ping link_timer, actor, &clb
223
- end.timeout(5) do
236
+ end.timeout(LinkTimeout) do
224
237
  clb.call
225
238
  end
226
239
  end
@@ -235,8 +248,8 @@ module Zactor
235
248
 
236
249
  def receive_reply(callback_id, *args)
237
250
  Zactor.logger.debug "Zactor: receive reply"
238
- if (callback = @callbacks[callback_id])
239
- if timeout = @timeouts[callback_id]
251
+ if (callback = @callbacks.delete(callback_id))
252
+ if timeout = @timeouts.delete(callback_id)
240
253
  EM.cancel_timer timeout
241
254
  end
242
255
  callback.call(*args)
@@ -247,10 +260,10 @@ module Zactor
247
260
  Zactor.logger.debug "Zactor: receive request"
248
261
  mes = Message.new self, :sender => sender, :callback_id => callback_id, :args => args
249
262
  if (event = self.class.events[event_name.to_sym])
250
- event.call owner, mes, *args
251
- else
252
- raise "Undefined event #{event_name}"
253
- end
263
+ event.call(owner, mes, *args)
264
+ else
265
+ raise "Undefined event #{event_name}"
266
+ end
254
267
  end
255
268
 
256
269
  def bson_actor
@@ -264,4 +277,4 @@ module Zactor
264
277
 
265
278
  end
266
279
 
267
- end
280
+ end
@@ -3,9 +3,8 @@ module Zactor
3
3
  include ZMQMEssages
4
4
 
5
5
  attr_accessor :actor
6
- def initialize(actor, endpoint)
7
- Zactor.logger.debug "ZactorPub (#{actor.actor}): starting"
8
- @actor = actor
6
+ def initialize(endpoint)
7
+ Zactor.logger.debug "ZactorPub (#{endpoint}): starting"
9
8
  @connection = Zactor.zmq.connect ZMQ::PUB, endpoint, self
10
9
  @socket = @connection.socket
11
10
  end
@@ -9,26 +9,7 @@ module Zactor
9
9
 
10
10
  def on_readable(socket, messages)
11
11
  Zactor.logger.debug "Broker: messages"
12
- @broker.pub.request messages
13
- end
14
-
15
- def close
16
- @connection.unbind
17
- rescue
18
- end
19
- end
20
-
21
- class BrokerPub
22
- include ZMQMEssages
23
- def initialize(broker)
24
- @broker = broker
25
- @connection = Zactor.zmq.bind ZMQ::PUB, "inproc://zactor_broker_pub", self
26
- @socket = @connection.socket
27
- end
28
-
29
- def request(messages)
30
- Zactor.logger.debug { "Broker: request #{messages.map(&:copy_out_string).inspect}" }
31
- send_messages messages
12
+ @broker.dispatch_request messages
32
13
  end
33
14
 
34
15
  def close
@@ -57,14 +38,43 @@ module Zactor
57
38
  attr_accessor :sub, :pub
58
39
  def initialize(params = {})
59
40
  Zactor.logger.info "Broker: starting"
60
- @pub = BrokerPub.new self
61
41
  @subs = []
62
42
  @subs << BrokerSub.new(self)
63
43
  @subs << BrokerPull.new(self, :host => params[:balancer]) if params[:balancer]
64
44
  end
65
45
 
46
+ def dispatch_request(messages)
47
+ to = messages.shift.copy_out_string
48
+ actor = Zactor.zactors[to]
49
+ return unless actor
50
+ Zactor.logger.debug "ZactorSub for #{actor.actor}: Messages!"
51
+ sender = messages.shift
52
+ case messages.shift.copy_out_string
53
+ when "reply"
54
+ reply actor, messages
55
+ when "request"
56
+ request actor, sender, messages
57
+ end
58
+ end
59
+
60
+ def request(actor, sender_mes, messages)
61
+ Zactor.logger.debug "ZactorSub for #{actor.actor}: request!"
62
+ sender = BSON.deserialize(sender_mes.copy_out_string)
63
+ callback_id = messages[0].copy_out_string
64
+ event = messages[1].copy_out_string
65
+ args = BSON.deserialize(messages[2].copy_out_string)['args']
66
+ actor.receive_request sender, event, callback_id, *args
67
+ end
68
+
69
+ def reply(actor, messages)
70
+ Zactor.logger.debug "ZactorSub for #{actor.actor}: reply!"
71
+ callback_id = messages[0].copy_out_string
72
+ if callback_id != ''
73
+ actor.receive_reply callback_id, *BSON.deserialize(messages[1].copy_out_string)['args']
74
+ end
75
+ end
76
+
66
77
  def finish
67
- @pub.close
68
78
  @subs.each(&:close)
69
79
  end
70
80
  end
@@ -1,3 +1,3 @@
1
1
  module Zactor
2
- VERSION = "0.0.7"
3
- end
2
+ VERSION = "0.0.8"
3
+ end
@@ -14,32 +14,13 @@ describe "Zactor actor" do
14
14
  let(:actor) { A.new.zactor }
15
15
  let(:sub) { Object.new }
16
16
  let(:local_pub) { Object.new }
17
- before do
18
- stub(actor).make_sub { sub }
19
- stub(actor).make_pub { local_pub }
20
- end
17
+
21
18
  it "должен зарегистрировать себя" do
22
19
  mock(Zactor).register actor
23
20
  actor.init
24
21
  end
25
22
 
26
- it "должен создать sub сокет" do
27
- mock(actor).make_sub { sub }
28
- actor.init
29
- actor.instance_eval { @sub }.should eq(sub)
30
- end
31
-
32
- it "должен создать pub сокет для локальных вызовов" do
33
- mock(actor).make_pub("inproc://zactor_broker_sub") { local_pub }
34
- actor.init
35
- actor.instance_eval { @pubs['0.0.0.0:8000'] }.should eq(local_pub)
36
- end
37
-
38
23
  describe "identity" do
39
- it "по-умолчанию" do
40
- actor.init
41
- actor.actor.should eq({ 'identity' => "actor.#{actor.owner.object_id}-0.0.0.0:8000", 'host' => '0.0.0.0:8000' })
42
- end
43
24
 
44
25
  it "с глобальным указанием" do
45
26
  A.zactor.identity "a"
@@ -61,61 +42,70 @@ describe "Zactor actor" do
61
42
  got.map(&:copy_out_string).should eq(expected.map(&:copy_out_string))
62
43
  end
63
44
 
45
+ def remote_pub(actor)
46
+ Zactor.pub(actor)
47
+ end
48
+
64
49
  before do
65
50
  actor.init
51
+ Zactor.instance_eval { @pubs['192.168.1.1:3000'] = Object.new }
66
52
  end
53
+
54
+
67
55
  describe "send_to" do
68
56
  it "должен отправить в локальный pub для локального объекта" do
57
+ remote_actor = Zactor.get_actor('b', :host => '192.168.1.1:3000')
69
58
  mes = messages { |m| }
70
- stub(local_pub).send_messages do |mes|
59
+ stub(remote_pub(remote_actor)).send_messages do |mes|
71
60
  assert_messages mes, messages { |m|
72
61
  m.str('b')
73
62
  m.str(actor.bson_actor)
74
63
  }
75
64
  end
76
- actor.send_to Zactor.get_actor('b')
65
+ actor.send_to remote_actor
77
66
  end
78
67
 
79
68
  it "должен отправить в удаленный pub для удаленного объекта, перед этим создав его" do
80
- remote_pub = Object.new
81
- mock(actor).make_pub("tcp://192.168.1.1:3000") { remote_pub }
82
- stub(remote_pub).send_messages do |mes|
69
+ remote_actor = Zactor.get_actor('b', :host => '192.168.1.1:3000')
70
+ stub(remote_pub(remote_actor)).send_messages do |mes|
83
71
  assert_messages mes, messages { |m| m.str('b'); m.str(actor.bson_actor) }
84
72
  end
85
- actor.send_to Zactor.get_actor('b', :host => '192.168.1.1:3000')
73
+ actor.send_to remote_actor
86
74
  end
87
75
  end
88
76
 
89
77
  describe "send_request" do
90
78
  it "должен отправлять сообщение типа request" do
91
- stub(local_pub).send_messages do |mes|
79
+ remote_actor = Zactor.get_actor('b', :host => '192.168.1.1:3000')
80
+ stub(remote_pub(remote_actor)).send_messages do |mes|
92
81
  assert_messages mes, messages { |m|
93
82
  m.str('b')
94
83
  m.str(actor.bson_actor)
95
-
84
+
96
85
  m.str 'request'
97
86
  m.str ""
98
87
  m.str "show"
99
88
  m.str BSON.serialize({ 'args' => ['foo', :bar] })
100
89
  }
101
90
  end
102
- actor.send_request Zactor.get_actor('b'), :show, 'foo', :bar
91
+ actor.send_request remote_actor, :show, 'foo', :bar
103
92
  end
104
93
  end
105
-
94
+
106
95
  describe "send_reply" do
107
96
  it "должен отправлять сообщение типа reply" do
108
- stub(local_pub).send_messages do |mes|
97
+ remote_actor = Zactor.get_actor('b', :host => '192.168.1.1:3000')
98
+ stub(remote_pub(remote_actor)).send_messages do |mes|
109
99
  assert_messages mes, messages { |m|
110
100
  m.str('b')
111
101
  m.str(actor.bson_actor)
112
-
102
+
113
103
  m.str 'reply'
114
104
  m.str 5
115
105
  m.str BSON.serialize({ 'args' => ['foo', :bar] })
116
106
  }
117
107
  end
118
- actor.send_reply Zactor.get_actor('b'), 5, 'foo', :bar
108
+ actor.send_reply remote_actor, 5, 'foo', :bar
119
109
  end
120
110
  end
121
111
 
@@ -15,6 +15,8 @@ describe "Zactor" do
15
15
 
16
16
  def ping(actor = Zactor.get_actor("b"))
17
17
  zactor.send_request actor, :ping do |res|
18
+ require 'ruby-debug'
19
+ debugger if $t
18
20
  reply
19
21
  end
20
22
  end
@@ -46,35 +48,43 @@ describe "Zactor" do
46
48
  end
47
49
  end
48
50
 
49
- after do
51
+ def em_start(timeout = 5, &blk)
52
+ em(timeout) do
53
+ Zactor.start 8000, :debug => true
54
+ blk.call
55
+ end
56
+ end
57
+
58
+
59
+ def em_done
50
60
  Zactor.clear
51
61
  Zactor.finish
62
+ EM.add_timer(0.1) { done }
52
63
  end
53
64
 
54
65
  it "B должен получить сообщение" do
55
- em do
56
- Zactor.start 8000, :debug => true
57
- Exchange::A.new.ping
66
+ em_start do
67
+ a = Exchange::A.new
58
68
  b = Exchange::B.new
59
- mock.proxy(b).receive { done }
69
+ mock.proxy(b).receive { em_done }
70
+ a.ping
71
+
60
72
  end
61
73
  end
62
74
 
63
75
  it "A должен получить ответ" do
64
- em do
65
- Zactor.start 8000, :debug => true
76
+ em_start do
66
77
  a = Exchange::A.new
67
- a.ping
68
78
  Exchange::B.new
69
- mock.proxy(a).reply { done }
79
+ mock.proxy(a).reply { em_done }
80
+ a.ping
70
81
  end
71
82
  end
72
83
 
73
84
  it "Если задан таймаут, то он должен срабатывать" do
74
- em(7) do
75
- Zactor.start 8000, :debug => true
85
+ em_start(7) do
76
86
  a = Exchange::A.new.ping.timeout(5) do
77
- done
87
+ em_done
78
88
  end
79
89
  end
80
90
  end
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.summary = "Zactor"
9
9
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
10
  s.authors = ["Andrew Rudenko"]
11
- s.date = %q{2011-03-24}
11
+ s.date = Time.now.strftime('%Y-%m-%d')
12
12
  s.description = %q{Zactor}
13
13
  s.email = %q{ceo@prepor.ru}
14
14
 
@@ -24,5 +24,6 @@ Gem::Specification.new do |s|
24
24
  s.add_dependency('bson', ["> 0.1"])
25
25
  s.add_dependency('bson_ext', ["> 0.1"])
26
26
  s.add_dependency('activesupport', ["> 0.1"])
27
+ s.add_dependency('uuid', ["> 0.1"])
27
28
  end
28
29
 
metadata CHANGED
@@ -1,128 +1,110 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: zactor
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 7
9
- version: 0.0.7
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.8
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Andrew Rudenko
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-03-24 00:00:00 +03:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2011-09-23 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: ffi
22
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &2161481500 !ruby/object:Gem::Requirement
23
17
  none: false
24
- requirements:
25
- - - ">"
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- - 1
30
- version: "0.1"
18
+ requirements:
19
+ - - ! '>'
20
+ - !ruby/object:Gem::Version
21
+ version: '0.1'
31
22
  type: :runtime
32
23
  prerelease: false
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
24
+ version_requirements: *2161481500
25
+ - !ruby/object:Gem::Dependency
35
26
  name: ruby-interface
36
- requirement: &id002 !ruby/object:Gem::Requirement
27
+ requirement: &2161480500 !ruby/object:Gem::Requirement
37
28
  none: false
38
- requirements:
39
- - - ">"
40
- - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
- version: "0"
29
+ requirements:
30
+ - - ! '>'
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
44
33
  type: :runtime
45
34
  prerelease: false
46
- version_requirements: *id002
47
- - !ruby/object:Gem::Dependency
35
+ version_requirements: *2161480500
36
+ - !ruby/object:Gem::Dependency
48
37
  name: ffi-rzmq
49
- requirement: &id003 !ruby/object:Gem::Requirement
38
+ requirement: &2161479420 !ruby/object:Gem::Requirement
50
39
  none: false
51
- requirements:
52
- - - ">"
53
- - !ruby/object:Gem::Version
54
- segments:
55
- - 0
56
- - 1
57
- version: "0.1"
40
+ requirements:
41
+ - - ! '>'
42
+ - !ruby/object:Gem::Version
43
+ version: '0.1'
58
44
  type: :runtime
59
45
  prerelease: false
60
- version_requirements: *id003
61
- - !ruby/object:Gem::Dependency
46
+ version_requirements: *2161479420
47
+ - !ruby/object:Gem::Dependency
62
48
  name: em-zeromq
63
- requirement: &id004 !ruby/object:Gem::Requirement
49
+ requirement: &2161478460 !ruby/object:Gem::Requirement
64
50
  none: false
65
- requirements:
66
- - - ">"
67
- - !ruby/object:Gem::Version
68
- segments:
69
- - 0
70
- - 1
71
- version: "0.1"
51
+ requirements:
52
+ - - ! '>'
53
+ - !ruby/object:Gem::Version
54
+ version: '0.1'
72
55
  type: :runtime
73
56
  prerelease: false
74
- version_requirements: *id004
75
- - !ruby/object:Gem::Dependency
57
+ version_requirements: *2161478460
58
+ - !ruby/object:Gem::Dependency
76
59
  name: bson
77
- requirement: &id005 !ruby/object:Gem::Requirement
60
+ requirement: &2161477700 !ruby/object:Gem::Requirement
78
61
  none: false
79
- requirements:
80
- - - ">"
81
- - !ruby/object:Gem::Version
82
- segments:
83
- - 0
84
- - 1
85
- version: "0.1"
62
+ requirements:
63
+ - - ! '>'
64
+ - !ruby/object:Gem::Version
65
+ version: '0.1'
86
66
  type: :runtime
87
67
  prerelease: false
88
- version_requirements: *id005
89
- - !ruby/object:Gem::Dependency
68
+ version_requirements: *2161477700
69
+ - !ruby/object:Gem::Dependency
90
70
  name: bson_ext
91
- requirement: &id006 !ruby/object:Gem::Requirement
71
+ requirement: &2161477000 !ruby/object:Gem::Requirement
92
72
  none: false
93
- requirements:
94
- - - ">"
95
- - !ruby/object:Gem::Version
96
- segments:
97
- - 0
98
- - 1
99
- version: "0.1"
73
+ requirements:
74
+ - - ! '>'
75
+ - !ruby/object:Gem::Version
76
+ version: '0.1'
100
77
  type: :runtime
101
78
  prerelease: false
102
- version_requirements: *id006
103
- - !ruby/object:Gem::Dependency
79
+ version_requirements: *2161477000
80
+ - !ruby/object:Gem::Dependency
104
81
  name: activesupport
105
- requirement: &id007 !ruby/object:Gem::Requirement
82
+ requirement: &2161476360 !ruby/object:Gem::Requirement
106
83
  none: false
107
- requirements:
108
- - - ">"
109
- - !ruby/object:Gem::Version
110
- segments:
111
- - 0
112
- - 1
113
- version: "0.1"
84
+ requirements:
85
+ - - ! '>'
86
+ - !ruby/object:Gem::Version
87
+ version: '0.1'
114
88
  type: :runtime
115
89
  prerelease: false
116
- version_requirements: *id007
90
+ version_requirements: *2161476360
91
+ - !ruby/object:Gem::Dependency
92
+ name: uuid
93
+ requirement: &2161475720 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>'
97
+ - !ruby/object:Gem::Version
98
+ version: '0.1'
99
+ type: :runtime
100
+ prerelease: false
101
+ version_requirements: *2161475720
117
102
  description: Zactor
118
103
  email: ceo@prepor.ru
119
104
  executables: []
120
-
121
105
  extensions: []
122
-
123
106
  extra_rdoc_files: []
124
-
125
- files:
107
+ files:
126
108
  - .document
127
109
  - .gitignore
128
110
  - .rspec
@@ -152,40 +134,34 @@ files:
152
134
  - spec/lib/zactor_spec.rb
153
135
  - spec/spec_helper.rb
154
136
  - zactor.gemspec
155
- has_rdoc: true
156
137
  homepage:
157
138
  licenses: []
158
-
159
139
  post_install_message:
160
140
  rdoc_options: []
161
-
162
- require_paths:
141
+ require_paths:
163
142
  - lib
164
- required_ruby_version: !ruby/object:Gem::Requirement
143
+ required_ruby_version: !ruby/object:Gem::Requirement
165
144
  none: false
166
- requirements:
167
- - - ">="
168
- - !ruby/object:Gem::Version
169
- hash: 1512131416648626830
170
- segments:
145
+ requirements:
146
+ - - ! '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ segments:
171
150
  - 0
172
- version: "0"
173
- required_rubygems_version: !ruby/object:Gem::Requirement
151
+ hash: -3905546204389082799
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
174
153
  none: false
175
- requirements:
176
- - - ">="
177
- - !ruby/object:Gem::Version
178
- segments:
179
- - 0
180
- version: "0"
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
181
158
  requirements: []
182
-
183
159
  rubyforge_project:
184
- rubygems_version: 1.3.7
160
+ rubygems_version: 1.8.5
185
161
  signing_key:
186
162
  specification_version: 3
187
163
  summary: Zactor
188
- test_files:
164
+ test_files:
189
165
  - spec/lib/actor_spec.rb
190
166
  - spec/lib/exchange_spec.rb
191
167
  - spec/lib/link_spec.rb