deepstream 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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: