skyfall 0.1.2 → 0.1.3
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/CHANGELOG.md +8 -0
- data/lib/skyfall/errors.rb +11 -0
- data/lib/skyfall/stream.rb +25 -8
- data/lib/skyfall/version.rb +1 -1
- data/lib/skyfall/websocket_message.rb +28 -9
- 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: b1d8eea31c1c63f4aabd513a470083862b653f4fb1ba5a0a638da1d9e8cba3af
|
|
4
|
+
data.tar.gz: 15e57a872800ad3a0c2a0f38be1ed31694617e82fe0981e1c9a1598c9f70e325
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 84544c24ff44ed583df898567b260db3b23517de6248b105f6199de49f2a3bcfaaada701bb62252c59a44af2845321637cfa4ab5061b9f8f800d27107fb2f83e
|
|
7
|
+
data.tar.gz: fb62308d1e517fdd257633a19f503dc9f9fce7d5b6b4d778a588c19facbe8c45ff60cca3e242ae9024c4975c9ca84326083e4eeddedd0da8d34f3ae9f647d05b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## [0.1.3] - 2023-07-04
|
|
2
|
+
|
|
3
|
+
- allow passing a previously saved cursor to websocket to replay any missed events
|
|
4
|
+
- the cursor is also kept in memory and automatically used when reconnecting
|
|
5
|
+
- added "connecting" callback with url as argument
|
|
6
|
+
- fixed connecting to websocket when endpoint is given as a string
|
|
7
|
+
- improved error handling during parsing
|
|
8
|
+
|
|
1
9
|
## [0.1.2] - 2023-06-15
|
|
2
10
|
|
|
3
11
|
- added rkey property for Operation
|
data/lib/skyfall/errors.rb
CHANGED
|
@@ -4,4 +4,15 @@ module Skyfall
|
|
|
4
4
|
|
|
5
5
|
class UnsupportedError < StandardError
|
|
6
6
|
end
|
|
7
|
+
|
|
8
|
+
class SubscriptionError < StandardError
|
|
9
|
+
attr_reader :error_type, :error_message
|
|
10
|
+
|
|
11
|
+
def initialize(error_type, error_message = nil)
|
|
12
|
+
@error_type = error_type
|
|
13
|
+
@error_message = error_message
|
|
14
|
+
|
|
15
|
+
super("Subscription error: #{error_type}" + (error_message ? " (#{error_message})" : ""))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
7
18
|
end
|
data/lib/skyfall/stream.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
require_relative 'websocket_message'
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
2
4
|
require 'websocket-client-simple'
|
|
3
5
|
|
|
4
6
|
module Skyfall
|
|
@@ -9,11 +11,12 @@ module Skyfall
|
|
|
9
11
|
:subscribe_repos => SUBSCRIBE_REPOS
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
attr_accessor :heartbeat_timeout, :heartbeat_interval
|
|
14
|
+
attr_accessor :heartbeat_timeout, :heartbeat_interval, :cursor
|
|
13
15
|
|
|
14
|
-
def initialize(server, endpoint)
|
|
16
|
+
def initialize(server, endpoint, cursor = nil)
|
|
15
17
|
@endpoint = check_endpoint(endpoint)
|
|
16
18
|
@server = check_hostname(server)
|
|
19
|
+
@cursor = cursor
|
|
17
20
|
@handlers = {}
|
|
18
21
|
@heartbeat_mutex = Mutex.new
|
|
19
22
|
@heartbeat_interval = 5
|
|
@@ -24,19 +27,21 @@ module Skyfall
|
|
|
24
27
|
def connect
|
|
25
28
|
return if @websocket
|
|
26
29
|
|
|
27
|
-
url =
|
|
30
|
+
url = build_websocket_url
|
|
28
31
|
handlers = @handlers
|
|
29
32
|
stream = self
|
|
30
33
|
|
|
34
|
+
handlers[:connecting]&.call(url)
|
|
35
|
+
|
|
31
36
|
@websocket = WebSocket::Client::Simple.connect(url) do |ws|
|
|
32
37
|
ws.on :message do |msg|
|
|
33
38
|
stream.notify_heartbeat
|
|
34
|
-
handlers[:raw_message]&.call(msg.data)
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
atp_message = Skyfall::WebsocketMessage.new(msg.data)
|
|
41
|
+
stream.cursor = atp_message.seq
|
|
42
|
+
|
|
43
|
+
handlers[:raw_message]&.call(msg.data)
|
|
44
|
+
handlers[:message]&.call(atp_message)
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
ws.on :open do
|
|
@@ -116,6 +121,10 @@ module Skyfall
|
|
|
116
121
|
@handlers[:raw_message] = block
|
|
117
122
|
end
|
|
118
123
|
|
|
124
|
+
def on_connecting(&block)
|
|
125
|
+
@handlers[:connecting] = block
|
|
126
|
+
end
|
|
127
|
+
|
|
119
128
|
def on_connect(&block)
|
|
120
129
|
@handlers[:connect] = block
|
|
121
130
|
end
|
|
@@ -135,6 +144,12 @@ module Skyfall
|
|
|
135
144
|
|
|
136
145
|
private
|
|
137
146
|
|
|
147
|
+
def build_websocket_url
|
|
148
|
+
url = "wss://#{@server}/xrpc/#{@endpoint}"
|
|
149
|
+
url += "?cursor=#{@cursor}" if @cursor
|
|
150
|
+
url
|
|
151
|
+
end
|
|
152
|
+
|
|
138
153
|
def check_endpoint(endpoint)
|
|
139
154
|
if endpoint.is_a?(String)
|
|
140
155
|
raise ArgumentError("Invalid endpoint name: #{endpoint}") if endpoint.strip.empty? || !endpoint.include?('.')
|
|
@@ -144,6 +159,8 @@ module Skyfall
|
|
|
144
159
|
else
|
|
145
160
|
raise ArgumentError("Endpoint should be a string or a symbol")
|
|
146
161
|
end
|
|
162
|
+
|
|
163
|
+
endpoint
|
|
147
164
|
end
|
|
148
165
|
|
|
149
166
|
def check_hostname(server)
|
data/lib/skyfall/version.rb
CHANGED
|
@@ -15,15 +15,7 @@ module Skyfall
|
|
|
15
15
|
attr_reader :type, :repo, :time, :seq, :commit, :prev, :blocks, :operations
|
|
16
16
|
|
|
17
17
|
def initialize(data)
|
|
18
|
-
|
|
19
|
-
raise DecodeError.new("Invalid number of objects: #{objects.length}") unless objects.length == 2
|
|
20
|
-
|
|
21
|
-
@type_object, @data_object = objects
|
|
22
|
-
raise DecodeError.new("Invalid object type: #{@type_object}") unless @type_object.is_a?(Hash)
|
|
23
|
-
raise DecodeError.new("Invalid object type: #{@data_object}") unless @data_object.is_a?(Hash)
|
|
24
|
-
raise DecodeError.new("Missing data: #{@type_object}") unless @type_object['op'] && @type_object['t']
|
|
25
|
-
raise DecodeError.new("Invalid message type: #{@type_object['t']}") unless @type_object['t'].start_with?('#')
|
|
26
|
-
raise UnsupportedError.new("Unexpected CBOR object: #{@type_object}") unless @type_object['op'] == 1
|
|
18
|
+
@type_object, @data_object = decode_cbor_objects(data)
|
|
27
19
|
|
|
28
20
|
@type = @type_object['t'][1..-1].to_sym
|
|
29
21
|
@operations = []
|
|
@@ -54,5 +46,32 @@ module Skyfall
|
|
|
54
46
|
vars = keys.map { |v| "#{v}=#{instance_variable_get(v).inspect}" }.join(", ")
|
|
55
47
|
"#<#{self.class}:0x#{object_id} #{vars}>"
|
|
56
48
|
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def decode_cbor_objects(data)
|
|
53
|
+
objects = CBOR.decode_sequence(data)
|
|
54
|
+
|
|
55
|
+
if objects.length < 2
|
|
56
|
+
raise DecodeError.new("Malformed message: #{objects.inspect}")
|
|
57
|
+
elsif objects.length > 2
|
|
58
|
+
raise DecodeError.new("Invalid number of objects: #{objects.length}")
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
type_object, data_object = objects
|
|
62
|
+
|
|
63
|
+
if data_object['error']
|
|
64
|
+
raise SubscriptionError.new(data_object['error'], data_object['message'])
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
raise DecodeError.new("Invalid object type: #{type_object}") unless type_object.is_a?(Hash)
|
|
68
|
+
raise UnsupportedError.new("Unexpected CBOR object: #{type_object}") unless type_object['op'] == 1
|
|
69
|
+
raise DecodeError.new("Missing data: #{type_object} #{objects.inspect}") unless type_object['op'] && type_object['t']
|
|
70
|
+
raise DecodeError.new("Invalid message type: #{type_object['t']}") unless type_object['t'].start_with?('#')
|
|
71
|
+
|
|
72
|
+
raise DecodeError.new("Invalid object type: #{data_object}") unless data_object.is_a?(Hash)
|
|
73
|
+
|
|
74
|
+
[type_object, data_object]
|
|
75
|
+
end
|
|
57
76
|
end
|
|
58
77
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: skyfall
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kuba Suder
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-07-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base32
|