ducts-client 0.2.0 → 0.4.5
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 +4 -4
- data/lib/ducts/client.rb +140 -65
- data/lib/ducts/client/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74c85c4fbbb4e225d647251a22a526545a3f4921b88921fb6fb779705b1fe4f1
|
4
|
+
data.tar.gz: f5396e8363fb5c31159be810b0631d45bfaca068143f136beb8a52e82f54ba93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2627825a0174c77e7070ae62a57bd6a74563fc35fb2882bc53fcee11434cb3341145c4735fc2deb7c2fc88bb5f624a776bff7e3110d0ca273b3fc93784882fb3
|
7
|
+
data.tar.gz: 040e53690914465287f0f59e275f9711454c46994cef7aaa68c9687c9e2d87e6d53bb31500aff28fa73aee1315581738dab025bc80ac06519838b24bdd72217e
|
data/lib/ducts/client.rb
CHANGED
@@ -6,6 +6,7 @@ require 'timeout'
|
|
6
6
|
require 'uri'
|
7
7
|
require 'net/http'
|
8
8
|
require 'json'
|
9
|
+
require 'stringio'
|
9
10
|
require 'faye/websocket'
|
10
11
|
require 'faye/websocket/api/event'
|
11
12
|
require 'msgpack'
|
@@ -56,6 +57,8 @@ module Ducts
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
60
|
+
DuctEventHandlerReturnValue = Struct.new(:source_rid, :source_eid, :source_data)
|
61
|
+
|
59
62
|
class ConnectionEventListener < DuctEventListener
|
60
63
|
attr_writer :onopen, :onclose, :onerror, :onmessage
|
61
64
|
def onopen(event)
|
@@ -118,7 +121,10 @@ module Ducts
|
|
118
121
|
|
119
122
|
@_last_rid = nil
|
120
123
|
@_ws = nil
|
121
|
-
@
|
124
|
+
@_waiting_message_completion = Hash.new
|
125
|
+
@_waiting_closed_completion = Array.new
|
126
|
+
@_loop_queues = Hash.new
|
127
|
+
@_divided_buffers = Hash.new
|
122
128
|
end
|
123
129
|
|
124
130
|
def next_rid
|
@@ -130,29 +136,13 @@ module Ducts
|
|
130
136
|
next_id
|
131
137
|
end
|
132
138
|
|
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 event_send(rid, eid, data)
|
142
|
-
_send(rid, eid, data)
|
143
|
-
end
|
144
|
-
|
145
|
-
def event_call(eid, data)
|
146
|
-
_call(eid, data)
|
147
|
-
end
|
148
|
-
|
149
|
-
def close
|
150
|
-
_close
|
151
|
-
end
|
152
|
-
|
153
139
|
def set_event_handler(event_id, &handler)
|
154
140
|
@_event_handler ||= {}
|
155
|
-
|
141
|
+
if handler
|
142
|
+
@_event_handler.store(event_id, handler)
|
143
|
+
else
|
144
|
+
@_event_handler.delete(event_id)
|
145
|
+
end
|
156
146
|
end
|
157
147
|
|
158
148
|
def state
|
@@ -163,16 +153,16 @@ module Ducts
|
|
163
153
|
end
|
164
154
|
end
|
165
155
|
|
166
|
-
|
167
|
-
|
168
|
-
if
|
169
|
-
|
170
|
-
|
156
|
+
def reconnect
|
157
|
+
completion = EM::Completion.new
|
158
|
+
if @_ws
|
159
|
+
completion.succeed(self)
|
160
|
+
return completion;
|
171
161
|
end
|
172
|
-
return if @_ws
|
173
162
|
Faye::WebSocket::Client.new(@WSD['websocket_url_reconnect']).tap do |ws|
|
174
163
|
ws.on(:open) do |event|
|
175
164
|
@_ws = ws
|
165
|
+
completion.succeed(self)
|
176
166
|
connection_event = DuctConnectionEvent.new('onopen', event)
|
177
167
|
_onreconnect(connection_event)
|
178
168
|
@connection_listener.onopen(connection_event)
|
@@ -192,10 +182,15 @@ module Ducts
|
|
192
182
|
@connection_listener.onerror(connection_event)
|
193
183
|
end
|
194
184
|
end
|
185
|
+
completion
|
195
186
|
end
|
196
187
|
|
197
|
-
def
|
198
|
-
|
188
|
+
def open(wsd_url, uuid = nil, **params)
|
189
|
+
completion = EM::Completion.new
|
190
|
+
if @_ws
|
191
|
+
completion.succeed(self)
|
192
|
+
return completion;
|
193
|
+
end
|
199
194
|
begin
|
200
195
|
query = '?uuid=' + (uuid || 'dummy') + params.map{ |k, v| "&#{k}=#{v}" }.join
|
201
196
|
uri = URI.parse(wsd_url + query)
|
@@ -210,6 +205,7 @@ module Ducts
|
|
210
205
|
Faye::WebSocket::Client.new(@WSD['websocket_url']).tap do |ws|
|
211
206
|
ws.on(:open) do |event|
|
212
207
|
@_ws = ws
|
208
|
+
completion.succeed(self)
|
213
209
|
connection_event = DuctConnectionEvent.new('onopen', event)
|
214
210
|
_onopen(connection_event)
|
215
211
|
@connection_listener.onopen(connection_event)
|
@@ -225,6 +221,19 @@ module Ducts
|
|
225
221
|
@connection_listener.onerror(connection_event)
|
226
222
|
end
|
227
223
|
ws.on(:close) do |event|
|
224
|
+
@_ws = nil
|
225
|
+
case event.code
|
226
|
+
when 1000
|
227
|
+
@_waiting_closed_completion.each do |waiting_closed_completion|
|
228
|
+
waiting_closed_completion.succeed(event)
|
229
|
+
end
|
230
|
+
else
|
231
|
+
p event.code
|
232
|
+
@_waiting_closed_completion.each do |waiting_closed_completion|
|
233
|
+
waiting_closed_completion.fail(event)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
@_waiting_closed_completion.clear
|
228
237
|
connection_event = DuctConnectionEvent.new('onclose', event)
|
229
238
|
@connection_listener.onclose(connection_event)
|
230
239
|
end
|
@@ -232,62 +241,70 @@ module Ducts
|
|
232
241
|
rescue => error
|
233
242
|
@connection_listener.onerror(DuctConnectionEvent.new('onerror', error))
|
234
243
|
end
|
244
|
+
completion
|
235
245
|
end
|
236
246
|
|
247
|
+
def event_send(rid, eid, data)
|
248
|
+
msgpack = [ rid, eid, data ].to_msgpack
|
249
|
+
@_ws.send(msgpack.chars.map(&:ord))
|
250
|
+
rid
|
251
|
+
end
|
252
|
+
|
253
|
+
def event_call(eid, data)
|
254
|
+
rid = next_rid
|
255
|
+
event_send(rid, eid, data)
|
256
|
+
warn Message.construct(Message::Level::WARNING, 'request ID is duplicated.') if @_waiting_message_completion.keys.include? rid
|
257
|
+
EM::Completion.new.tap { |completion| @_waiting_message_completion[rid] = completion }
|
258
|
+
end
|
259
|
+
|
260
|
+
def close
|
261
|
+
completion = EM::Completion.new
|
262
|
+
if @_ws
|
263
|
+
@_ws.close
|
264
|
+
@_waiting_closed_completion.push(completion)
|
265
|
+
else
|
266
|
+
completion.succeed(nil)
|
267
|
+
end
|
268
|
+
completion
|
269
|
+
end
|
270
|
+
|
271
|
+
private
|
237
272
|
def _onopen(event)
|
238
273
|
@_send_timestamp = Time.now.to_f
|
239
274
|
@_time_offset = 0
|
240
275
|
@_time_latency = 0
|
241
276
|
@_time_count = 0
|
242
|
-
set_event_handler(@EVENT['ALIVE_MONITORING']
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
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
|
277
|
+
set_event_handler(@EVENT['ALIVE_MONITORING'], &method(:_alive_monitoring_handler))
|
278
|
+
set_event_handler(@EVENT['LOOP_RESPONSE_START'], &method(:_loop_response_handler))
|
279
|
+
set_event_handler(@EVENT['LOOP_RESPONSE_NEXT'], &method(:_loop_response_handler))
|
280
|
+
set_event_handler(@EVENT['LOOP_RESPONSE_END'], &method(:_loop_response_end_handler))
|
281
|
+
set_event_handler(@EVENT['DIVIDED_RESPONSE_APPEND'], &method(:_divided_response_append_handler))
|
282
|
+
set_event_handler(@EVENT['DIVIDED_RESPONSE_END'], &method(:_divided_response_end_handler))
|
252
283
|
rid = next_rid
|
253
284
|
eid = @EVENT['ALIVE_MONITORING']
|
254
285
|
value = @_send_timestamp
|
255
|
-
|
286
|
+
event_send(rid, eid, value)
|
256
287
|
end
|
257
288
|
|
258
289
|
def _onreconnect(connection_event)
|
259
290
|
end
|
260
291
|
|
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
292
|
def _onmessage(connection_event)
|
283
293
|
begin
|
284
294
|
rid, eid, data = %i(rid eid data).map{ |name| connection_event.source.public_send(name) }
|
285
295
|
begin
|
286
296
|
@catchall_event_handler.call(rid, eid, data)
|
287
297
|
handle = @_event_handler[eid]
|
288
|
-
handle
|
289
|
-
handle.call(rid, eid, data)
|
290
|
-
|
298
|
+
handle ||= @uncaught_event_handler
|
299
|
+
handle.call(rid, eid, data).tap do |ret|
|
300
|
+
if ret.instance_of? DuctEventHandlerReturnValue
|
301
|
+
rid = ret.source_rid
|
302
|
+
eid = ret.source_eid
|
303
|
+
data = ret.source_data
|
304
|
+
end
|
305
|
+
end
|
306
|
+
return if rid.nil?
|
307
|
+
completion = @_waiting_message_completion.delete(rid)
|
291
308
|
if completion
|
292
309
|
if eid > 0
|
293
310
|
completion.succeed(data)
|
@@ -302,5 +319,63 @@ module Ducts
|
|
302
319
|
@event_error_handler.call(-1, -1, nil, error)
|
303
320
|
end
|
304
321
|
end
|
322
|
+
|
323
|
+
def _alive_monitoring_handler(rid, eid, data)
|
324
|
+
client_received = Time.now.to_f
|
325
|
+
server_sent, server_received = data
|
326
|
+
client_sent = @_send_timestamp
|
327
|
+
new_offset = ((server_received - client_sent) - (client_received - server_sent)) / 2
|
328
|
+
new_latency = ((client_received - client_sent) - (server_sent - server_received)) / 2
|
329
|
+
@_time_offset = (@_time_offset * @_time_count + new_offset) / (@_time_count + 1)
|
330
|
+
@_time_latency = (@_time_latency * @_time_count + new_latency) / (@_time_count + 1)
|
331
|
+
@_time_count += 1
|
332
|
+
end
|
333
|
+
|
334
|
+
def _loop_response_handler(rid, eid, data)
|
335
|
+
warn Message.construct(Message::Level::WARNING, 'loop response has error.') if eid.negative?
|
336
|
+
source_eid = data[1]
|
337
|
+
source_data = data[2]
|
338
|
+
@catchall_event_handler.call(rid, source_eid, source_data)
|
339
|
+
handle = @_event_handler[source_eid.abs]
|
340
|
+
handle ||= @uncaught_event_handler
|
341
|
+
ret = handle.call(rid, source_eid, source_data)
|
342
|
+
handled_source_data = (ret.instance_of? DuctEventHandlerReturnValue)? ret.source_data : source_data
|
343
|
+
@_loop_queues[rid] ||= EM::Queue.new
|
344
|
+
queue = @_loop_queues[rid]
|
345
|
+
queue.push(handled_source_data) if handled_source_data
|
346
|
+
DuctEventHandlerReturnValue.new(rid, source_eid, queue)
|
347
|
+
end
|
348
|
+
|
349
|
+
def _loop_response_end_handler(rid, eid, data)
|
350
|
+
warn Message.construct(Message::Level::WARNING, 'loop response end has error.') if eid.negative?
|
351
|
+
source_eid = data[1]
|
352
|
+
source_data = data[2]
|
353
|
+
warn Message.construct(Message::Level::WARNING, "loop response end has data: #{source_data}.") if source_data
|
354
|
+
@catchall_event_handler.call(rid, source_eid, source_data)
|
355
|
+
handle = @_event_handler[source_eid.abs]
|
356
|
+
handle ||= @uncaught_event_handler
|
357
|
+
handle.call(rid, source_eid, source_data)
|
358
|
+
queue = @_loop_queues.delete(rid)
|
359
|
+
queue.push(nil)
|
360
|
+
DuctEventHandlerReturnValue.new(rid, source_eid, source_eid)
|
361
|
+
end
|
362
|
+
|
363
|
+
def _divided_response_append_handler(rid, eid, data)
|
364
|
+
@_divided_buffers[rid] ||= StringIO.new('', 'wb').set_encoding(Encoding::ASCII_8BIT)
|
365
|
+
divided_buffer = @_divided_buffers[rid]
|
366
|
+
divided_buffer.write(data)
|
367
|
+
DuctEventHandlerReturnValue.new(nil, eid, nil)
|
368
|
+
end
|
369
|
+
|
370
|
+
def _divided_response_end_handler(rid, eid, data)
|
371
|
+
divided_buffer = @_divided_buffers.delete(rid)
|
372
|
+
divided_buffer.write(data)
|
373
|
+
source_rid, source_eid, source_data = MessagePack.unpack(divided_buffer.string)
|
374
|
+
@catchall_event_handler.call(source_rid, source_eid, source_data)
|
375
|
+
handle = @_event_handler[source_eid]
|
376
|
+
handle ||= @uncaught_event_handler
|
377
|
+
handle.call(source_rid, source_eid, source_data)
|
378
|
+
DuctEventHandlerReturnValue.new(source_rid, source_eid, source_data)
|
379
|
+
end
|
305
380
|
end
|
306
381
|
end
|
data/lib/ducts/client/version.rb
CHANGED
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.
|
4
|
+
version: 0.4.5
|
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-
|
11
|
+
date: 2021-08-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faye-websocket
|