deepstream 0.1.3 → 0.1.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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/deepstream.gemspec +1 -1
  3. data/lib/deepstream.rb +116 -30
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a9710ea0aad1261115011ffd5f931a228d82d4ac
4
- data.tar.gz: 8681f3f32c6351a7339532ddcf65f37b3606f9d8
3
+ metadata.gz: dd6d503c71516f071673b0c63d6ed0c3ecd0e055
4
+ data.tar.gz: 4e5087ecdc7b0420b0bccac544a6e1c0a7aa91d0
5
5
  SHA512:
6
- metadata.gz: 0e0f9e98828eef58e5e92f613eaec2f896252cbe441aff59d096c9baa17b995cc7bf4dc7a4c6e69da257272deb05574a217bb0805f67590de6e7d0c0510aad5f
7
- data.tar.gz: 79b04bcc09fa5fb50965551fe9e4e6dc18e5e1259106559f37a893188c18f940568735eb2a7bd0bf9f6ca548ca81fa037e54fac7ac9216a8f41a00fe60a074b5
6
+ metadata.gz: 88de53ede59b95a78f1f596d2aac53a86e43a789745bf42fd97f24351e0ec4d73d39077b49198931728d34b7721a2faed4c48e50b18b79685acc4b8286452bec
7
+ data.tar.gz: 1580071ce6dbbf29a2a7993348c243b69fea9da758b5c5e3f6aab705fdcb0574f2c2cbd093841e16210899f26e5d463c5c6e88290fbef92673f3ed46aae76751
data/deepstream.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "deepstream"
7
- spec.version = "0.1.3"
7
+ spec.version = "0.1.4"
8
8
  spec.authors = ["Currency-One S.A."]
9
9
  spec.email = ["piotr.szczudlak@currency-one.com"]
10
10
 
data/lib/deepstream.rb CHANGED
@@ -28,11 +28,16 @@ class Deepstream::Record
28
28
 
29
29
  def set(*args)
30
30
  if args.size == 1
31
- @client._write('R', 'U', @name, (@version += 1), JSON.dump(args[0]))
32
- @data = OpenStruct.new(args[0])
31
+ if @client._write('R', 'U', @name, (@version += 1), JSON.dump(args[0]))
32
+ @data = OpenStruct.new(args[0])
33
+ end
33
34
  else
34
35
  @client._write('R', 'P', @name, (@version += 1), args[0][0..-2], @client._typed(args[1]))
36
+ @data[args[0][0..-2]] = args[1]
35
37
  end
38
+ rescue => e
39
+ print "unable to set\n"
40
+ print "Error: ", e.message, "\n" if @client.verbose
36
41
  end
37
42
 
38
43
  def _patch(version, field, value)
@@ -48,19 +53,22 @@ class Deepstream::Record
48
53
  def method_missing(name, *args)
49
54
  unless @data.is_a?(Array)
50
55
  set(name, *args) if name[-1] == '='
51
- @data.send(name, *args)
56
+ @data[name] || @data[name[-1]]
52
57
  end
53
58
  end
54
59
  end
55
60
 
56
61
  class Deepstream::List < Deepstream::Record
57
62
  def add(record_name)
58
- if @data.is_a?(Array)
59
- @data.push record_name unless @data.include? record_name
60
- else
61
- @data = [record_name]
63
+ @data = [] unless @data.is_a?(Array)
64
+ unless @data.include? record_name
65
+ @data.push record_name
66
+ @client._write('R', 'U', @name, (@version += 1), JSON.dump(@data))
62
67
  end
63
- @client._write('R', 'U', @name, (@version += 1), JSON.dump(@data))
68
+ @data
69
+ rescue => e
70
+ print "unable to add ", @data.pop, "\n"
71
+ print "Error: ", e.message, "\n" if @client.verbose
64
72
  @data
65
73
  end
66
74
 
@@ -68,6 +76,11 @@ class Deepstream::List < Deepstream::Record
68
76
  @data.delete_if { |x| x == record_name }
69
77
  @client._write('R', 'U', @name, (@version += 1), JSON.dump(@data))
70
78
  @data
79
+ rescue => e
80
+ print "unable to remove ", record_name, "\n"
81
+ @data.push record_name
82
+ print "Error: ", e.message, "\n" if @client.verbose
83
+ @data
71
84
  end
72
85
 
73
86
  def all
@@ -84,14 +97,74 @@ class Deepstream::List < Deepstream::Record
84
97
  end
85
98
 
86
99
  class Deepstream::Client
87
- def initialize(address, port = 6021)
88
- @address, @port, @unread_msg, @event_callbacks, @records = address, port, nil, {}, {}
100
+ def initialize(address, port = 6021, credentials = {})
101
+ @address, @port, @unread_msg, @event_callbacks, @records, @max_timeout, @timeout = address, port, nil, {}, {}, 60, 1
102
+ connect(credentials)
103
+ end
104
+
105
+ attr_accessor :verbose, :max_timeout
106
+ attr_reader :connected
107
+
108
+ def _login(credentials)
109
+ _write("A", "REQ", credentials.to_json)
110
+ raise unless _read_socket == %w{A A}
111
+ end
112
+
113
+ def _read_socket(timeout: nil)
114
+ Timeout.timeout(timeout) do
115
+ @socket.gets(30.chr).tap { |m| break m.chomp(30.chr).split(31.chr) if m }
116
+ end
117
+ end
118
+
119
+ def connect(credentials)
120
+ return self if @connected
121
+ Thread.start do
122
+ Thread.current[:name] = "reader#{object_id}"
123
+ loop do
124
+ break if @connected # ensures only one thread remains after reconnection
125
+ begin
126
+ Timeout.timeout(2) { @socket = TCPSocket.new(@address, @port) }
127
+ _login(credentials)
128
+ @connected = true
129
+ print Time.now.to_s[/.+ .+ /], "Connected\n" if @verbose
130
+ Thread.start do
131
+ _sync_records
132
+ _resubscribe_events
133
+ end
134
+ loop do
135
+ @timeout = 1
136
+ begin
137
+ _process_msg(_read_socket(timeout: 10))
138
+ rescue TimeoutError
139
+ _write("heartbeat") # send anything to check if deepstream responds
140
+ _process_msg(_read_socket(timeout: 10))
141
+ end
142
+ end
143
+ rescue => e
144
+ @connected = false
145
+ @socket.close rescue nil
146
+ print Time.now.to_s[/.+ .+ /], "Can't connect to deepstream server\n" if @verbose
147
+ print "Error: ", e.message, "\n" if @verbose
148
+ sleep @timeout
149
+ @timeout = [@timeout * 1.2, @max_timeout].min
150
+ end
151
+ end
152
+ end
153
+ sleep 0.5
154
+ self
155
+ end
156
+
157
+ def disconnect
158
+ @connected = false
159
+ @socket.close rescue nil
160
+ Thread.list.find { |x| x[:name] == "reader#{object_id}" }.kill
161
+ self
89
162
  end
90
163
 
91
164
  def emit(event, value = nil, opts = { timeout: nil })
92
165
  result = nil
93
166
  Timeout::timeout(opts[:timeout]) do
94
- sleep 1 until (result = _write('E', 'EVT', event, _typed(value))) || opts[:timeout] == nil
167
+ sleep 1 until (result = _write('E', 'EVT', event, _typed(value)) rescue false) || opts[:timeout].nil?
95
168
  end
96
169
  result
97
170
  end
@@ -99,6 +172,9 @@ class Deepstream::Client
99
172
  def on(event, &block)
100
173
  _write_and_read('E', 'S', event)
101
174
  @event_callbacks[event] = block
175
+ rescue => e
176
+ print "Error: ", e.message, "\n" if @verbose
177
+ @event_callbacks[event] = block
102
178
  end
103
179
 
104
180
  def get(record_name)
@@ -107,16 +183,19 @@ class Deepstream::Client
107
183
 
108
184
  def get_record(record_name, list: nil)
109
185
  name = list ? "#{list}/#{record_name}" : record_name
186
+ if list
187
+ @records[list] ||= get_list(list)
188
+ @records[list].add(name)
189
+ end
110
190
  @records[name] ||= (
111
191
  _write_and_read('R', 'CR', name)
112
192
  msg = _read
113
193
  Deepstream::Record.new(self, name, _parse_data(msg[4]), msg[3].to_i)
114
194
  )
115
- if list
116
- @records[list] ||= get_list(list)
117
- @records[list].add(name)
118
- end
119
195
  @records[name]
196
+ rescue => e
197
+ print "Error: ", e.message, "\n" if @verbose
198
+ @records[name] = Deepstream::Record.new(self, name, OpenStruct.new, 0)
120
199
  end
121
200
 
122
201
  def get_list(list_name)
@@ -125,6 +204,9 @@ class Deepstream::Client
125
204
  msg = _read
126
205
  Deepstream::List.new(self, list_name, _parse_data(msg[4]), msg[3].to_i)
127
206
  )
207
+ rescue => e
208
+ print "Error: ", e.message, "\n" if @verbose
209
+ @records[list_name] = Deepstream::List.new(self, list_name, [], 0)
128
210
  end
129
211
 
130
212
  def delete(record_name)
@@ -133,22 +215,23 @@ class Deepstream::Client
133
215
  tmp.remove(record_name)
134
216
  end
135
217
  _write('R', 'D', record_name)
218
+ rescue => e
219
+ print "Error: ", e.message, "\n" if @verbose
220
+ false
136
221
  end
137
222
 
138
- def _open_socket
139
- Timeout.timeout(2) { @socket = TCPSocket.new(@address, @port) }
140
- Thread.start do
141
- loop { _process_msg(@socket.gets(30.chr).tap { |m| break m.chomp(30.chr).split(31.chr) if m }) }
223
+ def _resubscribe_events
224
+ @event_callbacks.keys.each do |event|
225
+ _write_and_read('E', 'S', event)
142
226
  end
143
- rescue
144
- print Time.now.to_s[/.+ .+ /], "Can't connect to deepstream server\n"
145
- raise
146
227
  end
147
228
 
148
- def _connect
149
- _open_socket
150
- @connected = true
151
- @connected = _write_and_read(%w{A REQ {}}) { |msg| msg == %w{A A} }
229
+ def _sync_records
230
+ @records.each do |name, record|
231
+ _write_and_read('R', 'CR', name)
232
+ msg = _read
233
+ @records[name]._update(msg[3].to_i, _parse_data(msg[4]))
234
+ end
152
235
  end
153
236
 
154
237
  def _write_and_read(*args)
@@ -158,10 +241,10 @@ class Deepstream::Client
158
241
  end
159
242
 
160
243
  def _write(*args)
161
- _connect unless @connected
162
244
  @socket.write(args.join(31.chr) + 30.chr)
163
- rescue
164
- @connected = false
245
+ rescue => e
246
+ raise "not connected" unless @connected
247
+ raise e
165
248
  end
166
249
 
167
250
  def _process_msg(msg)
@@ -171,7 +254,10 @@ class Deepstream::Client
171
254
  when %w{R U} then @records[msg[2]]._update(msg[3], _parse_data(msg[4]))
172
255
  when %w{R A} then @records.delete(msg[3]) if msg[2] == 'D'
173
256
  when %w{E A} then nil
174
- else @unread_msg = msg
257
+ when %w{X E} then nil
258
+ when [] then nil
259
+ else
260
+ @unread_msg = msg
175
261
  end
176
262
  end
177
263
 
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.1.3
4
+ version: 0.1.4
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: 2016-05-19 00:00:00.000000000 Z
11
+ date: 2016-06-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Basic ruby client for the deepstream.io server
14
14
  email: