deepstream 0.2.0 → 0.2.1
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/README.md +25 -17
- data/deepstream.gemspec +1 -1
- data/lib/deepstream/client.rb +57 -30
- data/lib/deepstream/error_handler.rb +2 -3
- data/lib/deepstream/event_handler.rb +14 -2
- data/lib/deepstream/helpers.rb +2 -1
- data/lib/deepstream/list.rb +4 -0
- data/lib/deepstream/message.rb +7 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f892fdc582aa7e27a3fe12d61e0f27662fb08dd
|
4
|
+
data.tar.gz: 49ce6f01d3ce6ad8cb382eab79679ac8cbe2a9f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96be6f3399854e1dfe56ed878c5aa42f6389ca11ff3e45b45a82dd74681594899ae3ff41c3af89fd6b01894ed497fb371c6bbe320113e3e7c9666043acb884cf
|
7
|
+
data.tar.gz: 8e313b9736f42b34681f0411e8cc4d13989805abe525563e0ef47e2ff82600282de8e2ae00dedcf92d1aff66f09cd08db8c13577dd3b16647cd725f7e379fa69
|
data/README.md
CHANGED
@@ -1,43 +1,49 @@
|
|
1
1
|
# deepstream-ruby
|
2
2
|
deepstream.io ruby client
|
3
3
|
|
4
|
-
|
5
4
|
### Install
|
6
5
|
|
7
6
|
```
|
8
7
|
gem install deepstream
|
9
8
|
```
|
10
9
|
|
11
|
-
|
12
10
|
### Usage
|
13
11
|
```ruby
|
14
|
-
ds = Deepstream::Client.new('localhost'
|
12
|
+
ds = Deepstream::Client.new('localhost',
|
13
|
+
autologin: false,
|
14
|
+
verbose: true,
|
15
|
+
credentials: { username: 'John', password: 'Doe' })
|
16
|
+
# or
|
17
|
+
ds = Deepstream::Client.new('ws://localhost:6020')
|
18
|
+
# or
|
19
|
+
ds = Deepstream::Client.new('ws://localhost:6020/deepstream')
|
20
|
+
|
21
|
+
# log in to the server
|
22
|
+
ds.login
|
23
|
+
# you can use new credentials too
|
24
|
+
ds.login(username: 'John', password: 'betterDoe')
|
25
|
+
|
26
|
+
# check if the websocket connection is opened
|
27
|
+
ds.connected?
|
28
|
+
|
29
|
+
# check if the client is logged in
|
30
|
+
ds.logged_in?
|
15
31
|
|
16
32
|
# Emit events
|
17
33
|
ds.emit 'my_event'
|
18
34
|
# or
|
19
35
|
ds.emit 'my_event', foo: 'bar', bar: 'foo'
|
20
|
-
# or
|
21
|
-
ds.emit 'my_event', {foo: 'bar', bar: 'foo'}, timeout: 3
|
22
|
-
# or
|
23
|
-
ds.emit 'my_event', nil, timeout: 3
|
24
|
-
|
25
36
|
|
26
37
|
# Subscribe to events
|
27
|
-
ds.on('some_event') do |msg|
|
38
|
+
ds.on('some_event') do |event_name, msg|
|
28
39
|
puts msg
|
29
40
|
end
|
30
41
|
|
31
|
-
|
32
42
|
# Get a record
|
33
43
|
foo = ds.get('foo')
|
44
|
+
bar = ds.get('bar', list: 'bar_list') # get a record within a namespace (this one automatically adds it to a list)
|
34
45
|
|
35
|
-
#
|
36
|
-
foo = ds.get_record('foo', list: 'bar') # record can also be accessed by ds.get('bar/foo')
|
37
|
-
|
38
|
-
# Update record
|
39
|
-
foo.bar = 'bar'
|
40
|
-
# or
|
46
|
+
# Update a record
|
41
47
|
foo.set('bar', 'bar')
|
42
48
|
|
43
49
|
# Set the whole record
|
@@ -46,13 +52,15 @@ foo.set(foo: 'foo', bar: 1)
|
|
46
52
|
# Get a list
|
47
53
|
foo = ds.get_list('bar')
|
48
54
|
|
49
|
-
# Add to list
|
55
|
+
# Add to the list
|
50
56
|
foo.add('foo')
|
51
57
|
|
52
58
|
# Remove from list
|
53
59
|
foo.remove('foo')
|
54
60
|
|
55
61
|
# Show record names on the list
|
62
|
+
foo.data
|
63
|
+
# or
|
56
64
|
foo.keys
|
57
65
|
|
58
66
|
# Access records on the list
|
data/deepstream.gemspec
CHANGED
data/lib/deepstream/client.rb
CHANGED
@@ -10,7 +10,7 @@ require 'deepstream/exceptions'
|
|
10
10
|
|
11
11
|
module Deepstream
|
12
12
|
class Client
|
13
|
-
attr_reader :
|
13
|
+
attr_reader :options, :state
|
14
14
|
|
15
15
|
include Celluloid
|
16
16
|
include Celluloid::Internals::Logger
|
@@ -19,7 +19,7 @@ module Deepstream
|
|
19
19
|
execute_block_on_receiver :on, :subscribe, :listen
|
20
20
|
|
21
21
|
def_delegators :@event_handler, :on, :emit, :subscribe, :unsubscribe, :listen, :resubscribe, :unlisten
|
22
|
-
def_delegators :@error_handler, :error, :on_error
|
22
|
+
def_delegators :@error_handler, :error, :on_error, :on_exception
|
23
23
|
def_delegators :@record_handler, :get, :set, :delete, :discard, :get_list
|
24
24
|
|
25
25
|
def initialize(url, options = {})
|
@@ -34,11 +34,13 @@ module Deepstream
|
|
34
34
|
@failed_reconnect_attempts = 0
|
35
35
|
@state = CONNECTION_STATE::CLOSED
|
36
36
|
Celluloid.logger.level = @options[:verbose] ? LOG_LEVEL::INFO : LOG_LEVEL::OFF
|
37
|
-
|
37
|
+
connect
|
38
38
|
end
|
39
39
|
|
40
40
|
def on_open
|
41
|
+
info("Websocket connection opened")
|
41
42
|
@state = CONNECTION_STATE::AWAITING_CONNECTION
|
43
|
+
@connection_requested, @deliberate_close = false
|
42
44
|
@failed_reconnect_attempts = 0
|
43
45
|
end
|
44
46
|
|
@@ -51,19 +53,19 @@ module Deepstream
|
|
51
53
|
when TOPIC::EVENT then @event_handler.on_message(message)
|
52
54
|
when TOPIC::ERROR then @error_handler.on_error(message)
|
53
55
|
when TOPIC::RECORD then @record_handler.on_message(message)
|
54
|
-
when TOPIC::RPC then raise
|
55
|
-
else raise
|
56
|
+
when TOPIC::RPC then raise(UnknownTopic, 'RPC is currently not implemented.')
|
57
|
+
else raise(UnknownTopic, message)
|
56
58
|
end
|
57
59
|
rescue => e
|
58
|
-
|
60
|
+
on_exception(e)
|
59
61
|
end
|
60
62
|
|
61
63
|
def on_close(code, reason)
|
62
|
-
info("Websocket connection closed: #{code.inspect}, #{reason.inspect}")
|
64
|
+
info("Websocket connection closed: code - #{code.inspect}, reason - #{reason.inspect}")
|
63
65
|
@state = CONNECTION_STATE::CLOSED
|
64
66
|
reconnect unless @deliberate_close
|
65
67
|
rescue => e
|
66
|
-
|
68
|
+
on_exception(e)
|
67
69
|
end
|
68
70
|
|
69
71
|
def login(credentials = @options[:credentials])
|
@@ -79,24 +81,28 @@ module Deepstream
|
|
79
81
|
end
|
80
82
|
self
|
81
83
|
rescue => e
|
82
|
-
|
84
|
+
on_exception(e)
|
83
85
|
self
|
84
86
|
end
|
85
87
|
|
86
88
|
def close
|
87
89
|
return unless connected?
|
90
|
+
@state = CONNECTION_STATE::CLOSED
|
88
91
|
@deliberate_close = true
|
89
92
|
@connection.close
|
90
93
|
@connection.terminate
|
91
|
-
@state = CONNECTION_STATE::CLOSED
|
92
94
|
rescue => e
|
93
|
-
|
95
|
+
on_exception(e)
|
94
96
|
end
|
95
97
|
|
96
98
|
def connected?
|
97
99
|
@state != CONNECTION_STATE::CLOSED
|
98
100
|
end
|
99
101
|
|
102
|
+
def reconnecting?
|
103
|
+
@state == CONNECTION_STATE::RECONNECTING
|
104
|
+
end
|
105
|
+
|
100
106
|
def logged_in?
|
101
107
|
@state == CONNECTION_STATE::OPEN
|
102
108
|
end
|
@@ -107,19 +113,26 @@ module Deepstream
|
|
107
113
|
|
108
114
|
def send_message(*args)
|
109
115
|
message = Message.parse(*args)
|
110
|
-
if !logged_in? && message.needs_authentication?
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
@connection.text(message.to_s)
|
116
|
-
end
|
116
|
+
return unable_to_send_message(message) if !logged_in? && message.needs_authentication?
|
117
|
+
info("Sending message: #{message.inspect}")
|
118
|
+
@connection.text(message.to_s)
|
119
|
+
rescue Errno::EPIPE
|
120
|
+
unable_to_send_message(message)
|
117
121
|
rescue => e
|
118
|
-
|
122
|
+
on_exception(e)
|
119
123
|
end
|
120
124
|
|
121
125
|
private
|
122
126
|
|
127
|
+
def unable_to_send_message(message)
|
128
|
+
@state = CONNECTION_STATE::CLOSED if logged_in?
|
129
|
+
unless message.expired?
|
130
|
+
info("Placing a message #{message.inspect} in the buffer, waiting for authentication")
|
131
|
+
@message_buffer << message
|
132
|
+
end
|
133
|
+
async.reconnect if !connected? && !@connection_requested
|
134
|
+
end
|
135
|
+
|
123
136
|
def connection_message(message)
|
124
137
|
case message.action
|
125
138
|
when ACTION::ACK then on_connection_ack
|
@@ -128,7 +141,7 @@ module Deepstream
|
|
128
141
|
when ACTION::PING then on_ping
|
129
142
|
when ACTION::REDIRECT then on_redirection(message)
|
130
143
|
when ACTION::REJECTION then on_rejection
|
131
|
-
else raise
|
144
|
+
else raise(UnknownAction, message)
|
132
145
|
end
|
133
146
|
end
|
134
147
|
|
@@ -136,7 +149,7 @@ module Deepstream
|
|
136
149
|
case message.action
|
137
150
|
when ACTION::ACK then on_login
|
138
151
|
when ACTION::ERROR then on_error(message)
|
139
|
-
else raise
|
152
|
+
else raise(UnknownAction, message)
|
140
153
|
end
|
141
154
|
end
|
142
155
|
|
@@ -157,8 +170,9 @@ module Deepstream
|
|
157
170
|
|
158
171
|
def on_login
|
159
172
|
@state = CONNECTION_STATE::OPEN
|
160
|
-
@message_buffer.each { |message| send_message(message) }.clear
|
173
|
+
@message_buffer.each { |message| send_message(message) unless message.expired? }.clear
|
161
174
|
every(@options[:heartbeat_interval]) { check_heartbeat } if @options[:heartbeat_interval]
|
175
|
+
resubscribe
|
162
176
|
end
|
163
177
|
|
164
178
|
def on_rejection
|
@@ -177,25 +191,38 @@ module Deepstream
|
|
177
191
|
connect(message.data.last)
|
178
192
|
end
|
179
193
|
|
180
|
-
def connect(url = @url, reraise = false)
|
194
|
+
def connect(url = @url, reraise = false, force = false)
|
195
|
+
return if @connection_requested && !force
|
196
|
+
info("Trying to connect to #{url}.")
|
197
|
+
@connection_requested = true
|
181
198
|
@connection = Celluloid::WebSocket::Client.new(url, Actor.current)
|
182
199
|
rescue => e
|
183
|
-
|
200
|
+
@connection_requested = false
|
201
|
+
reraise ? raise : on_exception(e)
|
184
202
|
end
|
185
203
|
|
186
204
|
def reconnect
|
187
|
-
|
188
|
-
if @failed_reconnect_attempts < @options[:max_reconnect_attempts]
|
189
|
-
|
190
|
-
|
205
|
+
info("Trying to reconnect to #{@url}")
|
206
|
+
if @options[:max_reconnect_attempts].nil? || @failed_reconnect_attempts < @options[:max_reconnect_attempts]
|
207
|
+
@state = CONNECTION_STATE::RECONNECTING
|
208
|
+
@login_requested = true
|
209
|
+
connect(@url, true, true)
|
210
|
+
sleep(5)
|
211
|
+
if !logged_in?
|
212
|
+
close
|
213
|
+
reconnect
|
214
|
+
end
|
191
215
|
else
|
192
216
|
@state = CONNECTION_STATE::ERROR
|
193
217
|
end
|
194
|
-
rescue Errno::ECONNREFUSED
|
218
|
+
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
|
195
219
|
@failed_reconnect_attempts += 1
|
196
220
|
on_error("Can't connect! Deepstream server unreachable on #{@url}")
|
221
|
+
info("Can't connect. Next attempt in #{reconnect_interval} seconds.")
|
197
222
|
sleep(reconnect_interval)
|
198
|
-
|
223
|
+
retry
|
224
|
+
rescue => e
|
225
|
+
on_exception(e)
|
199
226
|
end
|
200
227
|
|
201
228
|
def reconnect_interval
|
@@ -18,13 +18,12 @@ module Deepstream
|
|
18
18
|
else
|
19
19
|
message
|
20
20
|
end
|
21
|
-
puts @error
|
21
|
+
puts "#{@error}\n" unless @client.options[:debug]
|
22
22
|
end
|
23
23
|
|
24
24
|
def on_exception(exception)
|
25
25
|
raise exception if @client.options[:debug]
|
26
|
-
puts exception.message
|
27
|
-
puts exception.backtrace
|
26
|
+
puts "\n#{exception.message}\n#{exception.backtrace}\n"
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
@@ -17,6 +17,8 @@ module Deepstream
|
|
17
17
|
@ack_timeout_registry.add(event, "No ACK message received in time for #{event}")
|
18
18
|
end
|
19
19
|
@callbacks[event] = block
|
20
|
+
rescue => e
|
21
|
+
@client.on_exception(e)
|
20
22
|
end
|
21
23
|
alias subscribe on
|
22
24
|
|
@@ -25,12 +27,16 @@ module Deepstream
|
|
25
27
|
@listeners[pattern] = block
|
26
28
|
@client.send_message(TOPIC::EVENT, ACTION::LISTEN, pattern)
|
27
29
|
@ack_timeout_registry.add(pattern, "No ACK message received in time for #{pattern}")
|
30
|
+
rescue => e
|
31
|
+
@client.on_exception(e)
|
28
32
|
end
|
29
33
|
|
30
34
|
def unlisten(pattern)
|
31
35
|
pattern = pattern.is_a?(Regexp) ? pattern.source : pattern
|
32
36
|
@listeners.delete(pattern)
|
33
37
|
@client.send_message(TOPIC::EVENT, ACTION::UNLISTEN, pattern)
|
38
|
+
rescue => e
|
39
|
+
@client.on_exception(e)
|
34
40
|
end
|
35
41
|
|
36
42
|
def on_message(message)
|
@@ -43,18 +49,24 @@ module Deepstream
|
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
46
|
-
def emit(event, data = nil)
|
47
|
-
@client.send_message(TOPIC::EVENT, ACTION::EVENT, event, Helpers.to_deepstream_type(data))
|
52
|
+
def emit(event, data = nil, timeout: @client.options[:emit_timeout])
|
53
|
+
@client.send_message(TOPIC::EVENT, ACTION::EVENT, event, Helpers.to_deepstream_type(data), timeout: timeout)
|
54
|
+
rescue => e
|
55
|
+
@client.on_exception(e)
|
48
56
|
end
|
49
57
|
|
50
58
|
def unsubscribe(event)
|
51
59
|
@callbacks.delete(event)
|
52
60
|
@client.send_message(TOPIC::EVENT, ACTION::UNSUBSCRIBE, event)
|
61
|
+
rescue => e
|
62
|
+
@client.on_exception(e)
|
53
63
|
end
|
54
64
|
|
55
65
|
def resubscribe
|
56
66
|
@callbacks.keys.each { |event| @client.send_message(TOPIC::EVENT, ACTION::SUBSCRIBE, event) }
|
57
67
|
@listeners.keys.each { |pattern| @client.send_message(TOPIC::EVENT, ACTION::LISTEN, pattern) }
|
68
|
+
rescue => e
|
69
|
+
@client.on_exception(e)
|
58
70
|
end
|
59
71
|
|
60
72
|
private
|
data/lib/deepstream/helpers.rb
CHANGED
@@ -36,9 +36,10 @@ module Deepstream
|
|
36
36
|
autologin: true,
|
37
37
|
credentials: {},
|
38
38
|
heartbeat_interval: nil,
|
39
|
-
max_reconnect_attempts:
|
39
|
+
max_reconnect_attempts: nil,
|
40
40
|
max_reconnect_interval: 30,
|
41
41
|
reconnect_interval: 1,
|
42
|
+
emit_timeout: 0,
|
42
43
|
verbose: false,
|
43
44
|
debug: false
|
44
45
|
}
|
data/lib/deepstream/list.rb
CHANGED
data/lib/deepstream/message.rb
CHANGED
@@ -3,16 +3,17 @@ require 'deepstream/constants'
|
|
3
3
|
|
4
4
|
module Deepstream
|
5
5
|
class Message
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :action, :data, :topic, :sending_deadline
|
7
7
|
|
8
8
|
def self.parse(*args)
|
9
9
|
args.first.is_a?(self) ? args.first : new(*args)
|
10
10
|
end
|
11
11
|
|
12
|
-
def initialize(*args)
|
12
|
+
def initialize(*args, timeout: nil)
|
13
13
|
if args.one?
|
14
14
|
args = args.first.delete(MESSAGE_SEPARATOR).split(MESSAGE_PART_SEPARATOR)
|
15
15
|
end
|
16
|
+
@sending_deadline = Time.now + timeout if timeout
|
16
17
|
@topic, @action = args.take(2).map(&:to_sym)
|
17
18
|
@data = args.drop(2)
|
18
19
|
end
|
@@ -30,5 +31,9 @@ module Deepstream
|
|
30
31
|
def needs_authentication?
|
31
32
|
![TOPIC::CONNECTION, TOPIC::AUTH].include?(@topic)
|
32
33
|
end
|
34
|
+
|
35
|
+
def expired?
|
36
|
+
@sending_deadline && @sending_deadline < Time.now
|
37
|
+
end
|
33
38
|
end
|
34
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deepstream
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Currency-One S.A.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-02-
|
11
|
+
date: 2017-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid-websocket-client
|