ducts-client 0.1.2 → 0.4.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ffa6e977093a93d86411dfd32a683b6a693ca31f5c59f294be567cbbacca6902
4
- data.tar.gz: 13ed75278f6065bfb6256262aea24c0e5c23c581ab74ac10f8d1471c7cccb475
3
+ metadata.gz: e4ed02a6ed450d3495ea4d27af20b735e50959f1d95042dccf7afcca9331e079
4
+ data.tar.gz: f8a5f500b92af0ff4a6f3fca4f4590b480534976c412c969944919ecb7d5c261
5
5
  SHA512:
6
- metadata.gz: e93b5030eb9adbfd630558e355cb05ce9569a04e25eaca3b8be2554a75a62428ad8a98f7712c25575180ec4896e4b4ad0da3ea969e598ade52ee4c0cb2102727
7
- data.tar.gz: 7a322a50470f06e148f097e5102e0d45e527e07603441883e92ce7f919c6d3b3a0d47bb908f97778659bcf895bb552d5485bd1e388a89e2d069ea449ce363103
6
+ metadata.gz: e7621536c5e0dafabfa1d6f47eb0d69a6f96188251e2c83ddc33aeb1d58abc8a32d5ff1b88d7c39dad1c0040d063f428457e2fde85aca1be8c3d4af541ed06e9
7
+ data.tar.gz: 611bd6b7d8bf79eef1abff322f98723e9239a5f63a6f94443baf0a104263eb937d626d06ddaf8cda5884144deb72f4c50c005ff439ce0ce3bd69c64441c919fd
data/lib/ducts/client.rb CHANGED
@@ -56,6 +56,8 @@ module Ducts
56
56
  end
57
57
  end
58
58
 
59
+ DuctEventHandlerReturnValue = Struct.new(:value)
60
+
59
61
  class ConnectionEventListener < DuctEventListener
60
62
  attr_writer :onopen, :onclose, :onerror, :onmessage
61
63
  def onopen(event)
@@ -118,7 +120,9 @@ module Ducts
118
120
 
119
121
  @_last_rid = nil
120
122
  @_ws = nil
121
- @_waiting_completion = Hash.new
123
+ @_waiting_message_completion = Hash.new
124
+ @_waiting_closed_completion = Array.new
125
+ @_loop_queues = Hash.new
122
126
  end
123
127
 
124
128
  def next_rid
@@ -130,29 +134,13 @@ module Ducts
130
134
  next_id
131
135
  end
132
136
 
133
- def open(wsd_url, uuid = nil, **params)
134
- _open(wsd_url, uuid, **params)
135
- end
136
-
137
- def reconnect
138
- _reconnect
139
- end
140
-
141
- def send(rid, eid, data)
142
- _send(rid, eid, data)
143
- end
144
-
145
- def call(eid, data)
146
- _call(eid, data)
147
- end
148
-
149
- def close
150
- _close
151
- end
152
-
153
137
  def set_event_handler(event_id, &handler)
154
138
  @_event_handler ||= {}
155
- @_event_handler[event_id] = handler
139
+ if handler
140
+ @_event_handler.store(event_id, handler)
141
+ else
142
+ @_event_handler.delete(event_id)
143
+ end
156
144
  end
157
145
 
158
146
  def state
@@ -163,16 +151,16 @@ module Ducts
163
151
  end
164
152
  end
165
153
 
166
- private
167
- def _reconnect(wsd)
168
- if wsd
169
- @WSD = wsd
170
- @EVENT = @WSD['EVENT']
154
+ def reconnect
155
+ completion = EM::Completion.new
156
+ if @_ws
157
+ completion.succeed(self)
158
+ return completion;
171
159
  end
172
- return if @_ws
173
160
  Faye::WebSocket::Client.new(@WSD['websocket_url_reconnect']).tap do |ws|
174
161
  ws.on(:open) do |event|
175
162
  @_ws = ws
163
+ completion.succeed(self)
176
164
  connection_event = DuctConnectionEvent.new('onopen', event)
177
165
  _onreconnect(connection_event)
178
166
  @connection_listener.onopen(connection_event)
@@ -192,10 +180,15 @@ module Ducts
192
180
  @connection_listener.onerror(connection_event)
193
181
  end
194
182
  end
183
+ completion
195
184
  end
196
185
 
197
- def _open(wsd_url, uuid, **params)
198
- return if @_ws
186
+ def open(wsd_url, uuid = nil, **params)
187
+ completion = EM::Completion.new
188
+ if @_ws
189
+ completion.succeed(self)
190
+ return completion;
191
+ end
199
192
  begin
200
193
  query = '?uuid=' + (uuid || 'dummy') + params.map{ |k, v| "&#{k}=#{v}" }.join
201
194
  uri = URI.parse(wsd_url + query)
@@ -210,6 +203,7 @@ module Ducts
210
203
  Faye::WebSocket::Client.new(@WSD['websocket_url']).tap do |ws|
211
204
  ws.on(:open) do |event|
212
205
  @_ws = ws
206
+ completion.succeed(self)
213
207
  connection_event = DuctConnectionEvent.new('onopen', event)
214
208
  _onopen(connection_event)
215
209
  @connection_listener.onopen(connection_event)
@@ -225,6 +219,19 @@ module Ducts
225
219
  @connection_listener.onerror(connection_event)
226
220
  end
227
221
  ws.on(:close) do |event|
222
+ @_ws = nil
223
+ case event.code
224
+ when 1000
225
+ @_waiting_closed_completion.each do |waiting_closed_completion|
226
+ waiting_closed_completion.succeed(event)
227
+ end
228
+ else
229
+ p event.code
230
+ @_waiting_closed_completion.each do |waiting_closed_completion|
231
+ waiting_closed_completion.fail(event)
232
+ end
233
+ end
234
+ @_waiting_closed_completion.clear
228
235
  connection_event = DuctConnectionEvent.new('onclose', event)
229
236
  @connection_listener.onclose(connection_event)
230
237
  end
@@ -232,67 +239,69 @@ module Ducts
232
239
  rescue => error
233
240
  @connection_listener.onerror(DuctConnectionEvent.new('onerror', error))
234
241
  end
242
+ completion
243
+ end
244
+
245
+ def event_send(rid, eid, data)
246
+ msgpack = [ rid, eid, data ].to_msgpack
247
+ @_ws.send(msgpack.chars.map(&:ord))
248
+ rid
235
249
  end
236
250
 
251
+ def event_call(eid, data)
252
+ rid = next_rid
253
+ event_send(rid, eid, data)
254
+ warn Message.construct(Message::Level::WARNING, 'request ID is duplicated.') if @_waiting_message_completion.keys.include? rid
255
+ EM::Completion.new.tap { |completion| @_waiting_message_completion[rid] = completion }
256
+ end
257
+
258
+ def close
259
+ completion = EM::Completion.new
260
+ if @_ws
261
+ @_ws.close
262
+ @_waiting_closed_completion.push(completion)
263
+ else
264
+ completion.succeed(nil)
265
+ end
266
+ completion
267
+ end
268
+
269
+ private
237
270
  def _onopen(event)
238
271
  @_send_timestamp = Time.now.to_f
239
272
  @_time_offset = 0
240
273
  @_time_latency = 0
241
274
  @_time_count = 0
242
- set_event_handler(@EVENT['ALIVE_MONITORING']) do |rid, eid, data|
243
- client_received = Time.now.to_f
244
- server_sent, server_received = data
245
- client_sent = @_send_timestamp
246
- new_offset = ((server_received - client_sent) - (client_received - server_sent)) / 2
247
- new_latency = ((client_received - client_sent) - (server_sent - server_received)) / 2
248
- @_time_offset = (@_time_offset * @_time_count + new_offset) / (@_time_count + 1)
249
- @_time_latency = (@_time_latency * @_time_count + new_latency) / (@_time_count + 1)
250
- @_time_count += 1
251
- end
275
+ set_event_handler(@EVENT['ALIVE_MONITORING'], &method(:_alive_monitoring_handler))
276
+ set_event_handler(@EVENT['LOOP_RESPONSE_START'], &method(:_loop_response_handler))
277
+ set_event_handler(@EVENT['LOOP_RESPONSE_NEXT'], &method(:_loop_response_handler))
278
+ set_event_handler(@EVENT['LOOP_RESPONSE_END'], &method(:_loop_response_end_handler))
279
+ set_event_handler(@EVENT['DIVIDED_RESPONSE_APPEND'], &method(:_divided_response_append_handler))
280
+ set_event_handler(@EVENT['DIVIDED_RESPONSE_END'], &method(:_divided_response_end_handler))
252
281
  rid = next_rid
253
282
  eid = @EVENT['ALIVE_MONITORING']
254
283
  value = @_send_timestamp
255
- send(rid, eid, value)
284
+ event_send(rid, eid, value)
256
285
  end
257
286
 
258
287
  def _onreconnect(connection_event)
259
288
  end
260
289
 
261
- def _send(rid, eid, data)
262
- msgpack = [ rid, eid, data ].to_msgpack
263
- @_ws.send(msgpack.chars.map(&:ord))
264
- rid
265
- end
266
-
267
- def _call(eid, data)
268
- rid = next_rid
269
- _send(rid, eid, data)
270
- raise if @_waiting_completion.keys.include? rid
271
- EM::Completion.new.tap { |completion| @_waiting_completion[rid] = completion }
272
- end
273
-
274
- def _close
275
- begin
276
- @_ws.close if @_ws
277
- ensure
278
- @_ws = nil
279
- end
280
- end
281
-
282
290
  def _onmessage(connection_event)
283
291
  begin
284
292
  rid, eid, data = %i(rid eid data).map{ |name| connection_event.source.public_send(name) }
285
293
  begin
286
294
  @catchall_event_handler.call(rid, eid, data)
287
295
  handle = @_event_handler[eid]
288
- handle = @uncaught_event_handler unless handle
289
- handle.call(rid, eid, data)
290
- completion = @_waiting_completion.delete(rid)
296
+ handle ||= @uncaught_event_handler
297
+ ret = handle.call(rid, eid, data)
298
+ handled_data = (ret.instance_of? DuctEventHandlerReturnValue)? ret.value : data
299
+ completion = @_waiting_message_completion.delete(rid)
291
300
  if completion
292
301
  if eid > 0
293
- completion.succeed(data)
302
+ completion.succeed(handled_data)
294
303
  else
295
- completion.fail(DuctError.execption(data))
304
+ completion.fail(DuctError.exception(handled_data))
296
305
  end
297
306
  end
298
307
  rescue => error
@@ -302,5 +311,55 @@ module Ducts
302
311
  @event_error_handler.call(-1, -1, nil, error)
303
312
  end
304
313
  end
314
+
315
+ def _alive_monitoring_handler(rid, eid, data)
316
+ client_received = Time.now.to_f
317
+ server_sent, server_received = data
318
+ client_sent = @_send_timestamp
319
+ new_offset = ((server_received - client_sent) - (client_received - server_sent)) / 2
320
+ new_latency = ((client_received - client_sent) - (server_sent - server_received)) / 2
321
+ @_time_offset = (@_time_offset * @_time_count + new_offset) / (@_time_count + 1)
322
+ @_time_latency = (@_time_latency * @_time_count + new_latency) / (@_time_count + 1)
323
+ @_time_count += 1
324
+ end
325
+
326
+ def _loop_response_handler(rid, eid, data)
327
+ warn Message.construct(Message::Level::WARNING, 'loop response has error.') if eid.negative?
328
+ source_eid = data[1]
329
+ source_data = data[2]
330
+ @catchall_event_handler.call(rid, source_eid, source_data)
331
+ handle = @_event_handler[source_eid.abs]
332
+ handle ||= @uncaught_event_handler
333
+ ret = handle.call(rid, source_eid, source_data)
334
+ handled_source_data = (ret.instance_of? DuctEventHandlerReturnValue)? ret.value : source_data
335
+ @_loop_queues[rid] ||= EM::Queue.new
336
+ queue = @_loop_queues[rid]
337
+ queue.push(handled_source_data) if handled_source_data
338
+ DuctEventHandlerReturnValue.new(queue)
339
+ end
340
+
341
+ def _loop_response_end_handler(rid, eid, data)
342
+ warn Message.construct(Message::Level::WARNING, 'loop response end has error.') if eid.negative?
343
+ source_eid = data[1]
344
+ source_data = data[2]
345
+ warn Message.construct(Message::Level::WARNING, "loop response end has data: #{source_data}.") if source_data
346
+ @catchall_event_handler.call(rid, source_eid, source_data)
347
+ handle = @_event_handler[source_eid.abs]
348
+ handle ||= @uncaught_event_handler
349
+ handle.call(rid, source_eid, source_data)
350
+ queue = @_loop_queues.delete(rid)
351
+ queue.push(nil)
352
+ DuctEventHandlerReturnValue.new(source_eid)
353
+ end
354
+
355
+ def _divided_response_append_handler(rid, eid, data)
356
+ raise 'Not implemented.'
357
+ # TODO
358
+ end
359
+
360
+ def _divided_response_end_handler(rid, eid, data)
361
+ raise 'Not implemented.'
362
+ # TODO
363
+ end
305
364
  end
306
365
  end
@@ -4,8 +4,8 @@ module Ducts
4
4
  class Client
5
5
  module Version
6
6
  MAJOR = 0
7
- MINOR = 1
8
- PATCH = 2
7
+ MINOR = 4
8
+ PATCH = 4
9
9
  end
10
10
 
11
11
  VERSION = [ Version::MAJOR, Version::MINOR, Version::PATCH ].map(&:to_s).join('.')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ducts-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenshiro Ueda
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-19 00:00:00.000000000 Z
11
+ date: 2021-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye-websocket