matrix_sdk 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1de46ea35a8763e17d834c9395dc95a12c3084557085a0eb6b8e5f1fa25979a
4
- data.tar.gz: 13a55698bf72695e8e690d4d5f6618d7efe595f06c32c65580b10e9bf550724e
3
+ metadata.gz: 88e56c3775bf881fb720e4e262ff6073136204d26b72c03bb1bbd2a4138b90ee
4
+ data.tar.gz: c8f5223c4c0c4febda391e8320a90667b6438b92806ce0b9b7c251a506678730
5
5
  SHA512:
6
- metadata.gz: 919a27ee7fd758c382eafe3f8aad89c13da2a6cc6542ccd8bfe52d09186d93453b12406dfe6b03b6aa63d1898dbacfb6dbced4f4e9606722ad04df4f237cf600
7
- data.tar.gz: a8f5c0bc4fb07a089e0d1daebeb8996c6d36157550e73e3869a8bb55f25cc2c405a064654fc49c8bdb323f9d8c168b3c785e52b9f88fbc168ee29c152f7472a5
6
+ metadata.gz: 7ce44dc75ea446ff9f901d8309f58df4251c2c199540d27f086fbb77359974b5950da8c960540e3d7e89d1a40b7f264dfb9f1c5ad8462c4e94176fcb19fedc60
7
+ data.tar.gz: 0b2acb16c36524bac00528fe322984a587f8f0c951754d316148fbd337a5f0dafec6ce5daf3cdc5829673115bb96453b60475702633ca1e11718d5e78c8e37b0
data/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
+ ## 2.1.0 - 2020-05-22
2
+
3
+ - Adds unique query IDs as well as duration in API debug output, to make it easier to track long requests
4
+ - Finishes up MSC support, get sync over SSE working flawlessly
5
+ - Exposes the #listen_forever method in the client abstraction
6
+ - Fixes room access methods
7
+
1
8
  ## 2.0.1 - 2020-03-13
2
9
 
3
- - Add code for handling non-final MSC's in protocols
10
+ - Adds code for handling non-final MSC's in protocols
4
11
  - Currently implementing clients parts of MSC2018 for Sync over Server Sent Events
5
12
 
6
13
  ## 2.0.0 - 2020-02-14
@@ -161,6 +161,7 @@ module MatrixSdk
161
161
  def protocols
162
162
  self
163
163
  .class.included_modules
164
+ .reject { |m| m&.name.nil? }
164
165
  .select { |m| m.name.start_with? 'MatrixSdk::Protocols::' }
165
166
  .map { |m| m.name.split('::').last.to_sym }
166
167
  end
@@ -272,14 +273,20 @@ module MatrixSdk
272
273
  loop do
273
274
  raise MatrixConnectionError, "Server still too busy to handle request after #{failures} attempts, try again later" if failures >= 10
274
275
 
275
- print_http(request)
276
+ req_id = ('A'..'Z').to_a.sample(4).join
277
+
278
+ print_http(request, id: req_id)
276
279
  begin
280
+ dur_start = Time.now
277
281
  response = http.request request
278
- rescue EOFError => e
282
+ dur_end = Time.now
283
+ duration = dur_end - dur_start
284
+ rescue EOFError
279
285
  logger.error 'Socket closed unexpectedly'
280
- raise e
286
+ raise
281
287
  end
282
- print_http(response)
288
+ print_http(response, duration: duration, id: req_id)
289
+
283
290
  data = JSON.parse(response.body, symbolize_names: true) rescue nil
284
291
 
285
292
  if response.is_a? Net::HTTPTooManyRequests
@@ -298,17 +305,26 @@ module MatrixSdk
298
305
  end
299
306
  end
300
307
 
308
+ # Generate a transaction ID
309
+ #
310
+ # @return [String] An arbitrary transaction ID
311
+ def transaction_id
312
+ ret = @transaction_id ||= 0
313
+ @transaction_id = @transaction_id.succ
314
+ ret
315
+ end
316
+
301
317
  private
302
318
 
303
- def print_http(http, body: true)
319
+ def print_http(http, body: true, duration: nil, id: nil)
304
320
  return unless logger.debug?
305
321
 
306
322
  if http.is_a? Net::HTTPRequest
307
- dir = '>'
323
+ dir = "#{id ? id + ' : ' : nil}>"
308
324
  logger.debug "#{dir} Sending a #{http.method} request to `#{http.path}`:"
309
325
  else
310
- dir = '<'
311
- logger.debug "#{dir} Received a #{http.code} #{http.message} response:"
326
+ dir = "#{id ? id + ' : ' : nil}<"
327
+ logger.debug "#{dir} Received a #{http.code} #{http.message} response:#{duration ? " [#{(duration * 1000).to_i}ms]" : nil}"
312
328
  end
313
329
  http.to_hash.map { |k, v| "#{k}: #{k == 'authorization' ? '[ REDACTED ]' : v.join(', ')}" }.each do |h|
314
330
  logger.debug "#{dir} #{h}"
@@ -324,12 +340,6 @@ module MatrixSdk
324
340
  logger.warn "#{e.class} occured while printing request debug; #{e.message}\n#{e.backtrace.join "\n"}"
325
341
  end
326
342
 
327
- def transaction_id
328
- ret = @transaction_id ||= 0
329
- @transaction_id = @transaction_id.succ
330
- ret
331
- end
332
-
333
343
  def api_to_path(api)
334
344
  # TODO: <api>_current / <api>_latest
335
345
  "/_matrix/#{api.to_s.split('_').join('/')}"
@@ -424,12 +424,26 @@ module MatrixSdk
424
424
 
425
425
  @should_listen = true
426
426
  if api.protocol?(:MSC) && api.msc2108?
427
+ params[:filter] = sync_filter unless params.key? :filter
428
+ params[:filter] = params[:filter].to_json unless params[:filter].nil? || params[:filter].is_a?(String)
427
429
  params[:since] = @next_batch if @next_batch
428
- thread = api.msc2108_sync_sse(params) do |data, event:, id:|
429
- logger.debug "Handling SSE event '#{event}' from '#{id}'"
430
+
431
+ errors = 0
432
+ thread, cancel_token = api.msc2108_sync_sse(params) do |data, event:, id:|
430
433
  @next_batch = id if id
431
- handle_sync_response(data) if event.to_sym == :sync
434
+ if event.to_sym == :sync
435
+ handle_sync_response(data)
436
+ errors = 0
437
+ elsif event.to_sym == :sync_error
438
+ logger.error "SSE Sync error received; #{data.type}: #{data.message}"
439
+ errors += 1
440
+
441
+ # TODO: Allow configuring
442
+ raise 'Aborting due to excessive errors' if errors >= 5
443
+ end
432
444
  end
445
+
446
+ @should_listen = cancel_token
433
447
  else
434
448
  thread = Thread.new { listen_forever(params) }
435
449
  end
@@ -441,8 +455,15 @@ module MatrixSdk
441
455
  def stop_listener_thread
442
456
  return unless @sync_thread
443
457
 
444
- @should_listen = false
445
- @sync_thread.join if @sync_thread.alive?
458
+ if @should_listen.is_a? Hash
459
+ @should_listen[:run] = false
460
+ else
461
+ @should_listen = false
462
+ end
463
+ if @sync_thread.alive?
464
+ ret = @sync_thread.join(2)
465
+ @sync_thread.kill unless ret
466
+ end
446
467
  @sync_thread = nil
447
468
  end
448
469
 
@@ -503,8 +524,6 @@ module MatrixSdk
503
524
  end
504
525
  end
505
526
 
506
- private
507
-
508
527
  def listen_forever(timeout: 30, bad_sync_timeout: 5, sync_interval: 30, **params)
509
528
  orig_bad_sync_timeout = bad_sync_timeout + 0
510
529
  while @should_listen
@@ -528,6 +547,8 @@ module MatrixSdk
528
547
  fire_error(ErrorEvent.new(e, :listener_thread))
529
548
  end
530
549
 
550
+ private
551
+
531
552
  def post_authentication(data)
532
553
  @mxid = data[:user_id]
533
554
  @api.access_token = data[:access_token]
@@ -2,16 +2,13 @@
2
2
 
3
3
  # Preliminary support for unmerged MSCs (Matrix Spec Changes)
4
4
  module MatrixSdk::Protocols::MSC
5
- def self.included(_)
6
- @msc = {}
7
- end
8
-
9
5
  def refresh_mscs
10
6
  @msc = {}
11
7
  end
12
8
 
13
9
  # Check if there's support for MSC2108 - Sync over Server Sent Events
14
10
  def msc2108?
11
+ @msc ||= {}
15
12
  @msc[2108] ||= \
16
13
  begin
17
14
  request(:get, :client_r0, '/sync/sse', skip_auth: true, headers: { accept: 'text/event-stream' })
@@ -20,13 +17,13 @@ module MatrixSdk::Protocols::MSC
20
17
  rescue MatrixSdk::MatrixRequestError
21
18
  false
22
19
  end
20
+ rescue StandardError => e
21
+ logger.debug "Failed to check MSC2108 status;\n#{e.inspect}"
22
+ false
23
23
  end
24
24
 
25
25
  # Sync over Server Sent Events - MSC2108
26
26
  #
27
- # @note With the default Ruby Net::HTTP server, body fragments are cached up to 16kB,
28
- # which will result in large batches and delays if your filters trim a lot of data.
29
- #
30
27
  # @example Syncing over SSE
31
28
  # @since = 'some token'
32
29
  # api.msc2108_sync_sse(since: @since) do |data, event:, id:|
@@ -38,10 +35,11 @@ module MatrixSdk::Protocols::MSC
38
35
  #
39
36
  # @see Protocols::CS#sync
40
37
  # @see https://github.com/matrix-org/matrix-doc/pull/2108/
38
+ # rubocop:disable Metrics/MethodLength
41
39
  def msc2108_sync_sse(since: nil, **params, &on_data)
42
40
  raise ArgumentError, 'Must be given a block accepting two args - data and { event:, id: }' \
43
41
  unless on_data.is_a?(Proc) && on_data.arity == 2
44
- raise MatrixNotAuthorizedError unless access_token
42
+ raise 'Needs to be logged in' unless access_token # TODO: Better error
45
43
 
46
44
  query = params.select do |k, _v|
47
45
  %i[filter full_state set_presence].include? k
@@ -53,20 +51,52 @@ module MatrixSdk::Protocols::MSC
53
51
  u.query = URI.encode_www_form(query)
54
52
  end)
55
53
  req['accept'] = 'text/event-stream'
54
+ req['accept-encoding'] = 'identity' # Disable compression on the SSE stream
56
55
  req['authorization'] = "Bearer #{access_token}"
57
56
  req['last-event-id'] = since if since
58
57
 
58
+ cancellation_token = { run: true }
59
+
59
60
  # rubocop:disable Metrics/BlockLength
60
- thread = Thread.new do
61
+ thread = Thread.new(cancellation_token) do |ctx|
61
62
  print_http(req)
62
63
  http.request req do |response|
64
+ break unless ctx[:run]
65
+
63
66
  print_http(response, body: false)
64
67
  raise MatrixRequestError.new_by_code(JSON.parse(response.body, symbolize_names: true), response.code) unless response.is_a? Net::HTTPSuccess
65
68
 
69
+ # Override buffer size for BufferedIO
70
+ socket = response.instance_variable_get :@socket
71
+ if socket.is_a? Net::BufferedIO
72
+ socket.instance_eval do
73
+ def rbuf_fill
74
+ bufsize_override = 1024
75
+ loop do
76
+ case rv = @io.read_nonblock(bufsize_override, exception: false)
77
+ when String
78
+ @rbuf << rv
79
+ rv.clear
80
+ return
81
+ when :wait_readable
82
+ @io.to_io.wait_readable(@read_timeout) || raise(Net::ReadTimeout)
83
+ when :wait_writable
84
+ @io.to_io.wait_writable(@read_timeout) || raise(Net::ReadTimeout)
85
+ when nil
86
+ raise EOFError, 'end of file reached'
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ stream_id = ('A'..'Z').to_a.sample(4).join
94
+
95
+ logger.debug "MSC2108 : #{stream_id} : Starting SSE stream."
96
+
66
97
  buffer = ''
67
98
  response.read_body do |chunk|
68
99
  buffer += chunk
69
- logger.debug "< MSC2108: Received #{chunk.length}B of data."
70
100
 
71
101
  while (index = buffer.index(/\r\n\r\n|\n\n/))
72
102
  stream = buffer.slice!(0..index)
@@ -86,20 +116,32 @@ module MatrixSdk::Protocols::MSC
86
116
  /^id:(.+)$/.match(part) do |m_id|
87
117
  id = m_id[1].strip
88
118
  end
119
+ /^:(.+)$/.match(part) do |m_comment|
120
+ logger.debug "MSC2108 : #{stream_id} : Received comment '#{m_comment[1].strip}'"
121
+ end
89
122
  end
90
123
 
91
- data = JSON.parse(data, symbolize_names: true)
124
+ if %w[sync sync_error].include? event
125
+ data = JSON.parse(data, symbolize_names: true)
126
+ yield((MatrixSdk::Response.new self, data), event: event, id: id)
127
+ elsif event
128
+ logger.info "MSC2108 : #{stream_id} : Received unknown event '#{event}'; #{data}"
129
+ end
130
+ end
92
131
 
93
- yield((MatrixSdk::Response.new self, data), event: event, id: id)
132
+ unless ctx[:run]
133
+ socket.close
134
+ break
94
135
  end
95
136
  end
137
+ break unless ctx[:run]
96
138
  end
97
139
  end
98
140
  # rubocop:enable Metrics/BlockLength
99
141
 
100
- thread.abort_on_exception = true
101
142
  thread.run
102
143
 
103
- thread
144
+ [thread, cancellation_token]
104
145
  end
146
+ # rubocop:enable Metrics/MethodLength
105
147
  end
@@ -590,7 +590,7 @@ module MatrixSdk
590
590
  #
591
591
  # @param join_rule [:invite,:public] The join rule of the room
592
592
  def join_rule=(join_rule)
593
- client.api.set_join_rule(id, join_rule)
593
+ client.api.set_room_join_rules(id, join_rule)
594
594
  @join_rule = join_rule
595
595
  end
596
596
 
@@ -606,7 +606,7 @@ module MatrixSdk
606
606
  #
607
607
  # @param guest_access [:can_join,:forbidden] The new guest access status of the room
608
608
  def guest_access=(guest_access)
609
- client.api.set_guest_access(id, guest_access)
609
+ client.api.set_room_guest_access(id, guest_access)
610
610
  @guest_access = guest_access
611
611
  end
612
612
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MatrixSdk
4
- VERSION = '2.0.1'
4
+ VERSION = '2.1.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matrix_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Olofsson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-13 00:00:00.000000000 Z
11
+ date: 2020-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mocha