volcano-sdk 0.31.0 → 0.32.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 +13 -7
- data/lib/volcano/database.rb +28 -37
- data/lib/volcano/durable.rb +6 -6
- data/lib/volcano/durable_models.rb +65 -22
- data/lib/volcano/function_auth.rb +9 -2
- data/lib/volcano/functions.rb +18 -15
- data/lib/volcano/immutable_request_value.rb +21 -0
- data/lib/volcano/logs.rb +14 -9
- data/lib/volcano/models.rb +55 -22
- data/lib/volcano/realtime/broadcast_delivery.rb +26 -2
- data/lib/volcano/realtime/channel_callbacks.rb +23 -15
- data/lib/volcano/realtime/channel_lifecycle.rb +9 -9
- data/lib/volcano/realtime/connection.rb +9 -5
- data/lib/volcano/realtime/connection_callbacks.rb +5 -1
- data/lib/volcano/realtime/lifecycle.rb +2 -1
- data/lib/volcano/realtime/postgres_batch.rb +11 -3
- data/lib/volcano/realtime/postgres_changes.rb +33 -16
- data/lib/volcano/realtime/postgres_database.rb +14 -1
- data/lib/volcano/realtime/postgres_delivery.rb +6 -1
- data/lib/volcano/realtime/postgres_expansion.rb +10 -4
- data/lib/volcano/realtime/presence.rb +18 -4
- data/lib/volcano/realtime/presence_state.rb +23 -6
- data/lib/volcano/realtime/protocol.rb +14 -9
- data/lib/volcano/realtime/protocol_dispatch.rb +25 -7
- data/lib/volcano/realtime/protocol_io.rb +8 -4
- data/lib/volcano/realtime/protocol_lifecycle.rb +2 -0
- data/lib/volcano/realtime/protocol_publication_dispatch.rb +12 -10
- data/lib/volcano/realtime/protocol_recovery.rb +7 -3
- data/lib/volcano/realtime/protocol_recovery_dispatch.rb +2 -0
- data/lib/volcano/realtime/reconnect.rb +4 -1
- data/lib/volcano/realtime.rb +122 -99
- data/lib/volcano/session.rb +14 -3
- data/lib/volcano/transport.rb +53 -11
- data/lib/volcano/user.rb +12 -7
- data/lib/volcano/version.rb +1 -1
- data/lib/volcano.rb +1 -0
- data/sig/auth_session_records.rbs +1 -1
- data/sig/client.rbs +15 -0
- data/sig/core_facades.rbs +81 -0
- data/sig/durable_records.rbs +1 -1
- data/sig/locks.rbs +10 -0
- data/sig/realtime.rbs +45 -0
- data/sig/realtime_postgres_change.rbs +1 -2
- data/sig/user.rbs +1 -1
- metadata +6 -1
data/lib/volcano/realtime.rb
CHANGED
|
@@ -32,134 +32,148 @@ module Volcano
|
|
|
32
32
|
|
|
33
33
|
# Recursively snapshots JSON-compatible values for callback and state safety.
|
|
34
34
|
module Immutable
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def optional(value)
|
|
38
|
-
value && call(value)
|
|
35
|
+
def self.optional(value)
|
|
36
|
+
value && snapshot(value)
|
|
39
37
|
end
|
|
40
38
|
|
|
41
|
-
def call(value)
|
|
39
|
+
def self.call(value) = snapshot(value)
|
|
40
|
+
|
|
41
|
+
def self.snapshot(value)
|
|
42
42
|
case value
|
|
43
43
|
when Hash then call_hash(value)
|
|
44
|
-
when Array then value.map { |child|
|
|
44
|
+
when Array then value.map { |child| snapshot(child) }.freeze
|
|
45
45
|
when String then value.dup.freeze
|
|
46
46
|
else value.freeze
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
def call_hash(value)
|
|
51
|
-
value.to_h { |key, item| [
|
|
50
|
+
def self.call_hash(value)
|
|
51
|
+
value.to_h { |key, item| [snapshot(key), snapshot(item)] }.freeze
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
private_constant :Immutable
|
|
55
55
|
|
|
56
|
-
PresenceInfo = Data.define(:client, :user, :data)
|
|
56
|
+
PresenceInfo = Data.define(:client, :user, :data)
|
|
57
|
+
|
|
58
|
+
# An immutable snapshot of one presence client.
|
|
59
|
+
class PresenceInfo
|
|
60
|
+
# @dynamic client, user, data, members, with, to_h, deconstruct, deconstruct_keys
|
|
61
|
+
# @dynamic self.[], self.members
|
|
57
62
|
def initialize(client:, user: nil, data: {})
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
)
|
|
63
|
+
client = Immutable.call(client.to_s)
|
|
64
|
+
user = user.nil? ? nil : Immutable.call(user.to_s)
|
|
65
|
+
data = Immutable.call(data)
|
|
66
|
+
super
|
|
63
67
|
end
|
|
64
68
|
end
|
|
65
69
|
|
|
66
70
|
CHANNEL_TYPES = %i[broadcast presence postgres].freeze
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@
|
|
71
|
-
@
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
# Owns the public realtime facade and its channel collection.
|
|
73
|
+
module Core
|
|
74
|
+
# @dynamic initialize_postgres_database, connect_protocol, close_protocol, public_error
|
|
75
|
+
# @dynamic protocol_error, open_socket, default_reconnect_delay, __send__
|
|
76
|
+
def initialize(client, api_url:, socket_factory: nil, reconnect_delay: nil)
|
|
77
|
+
@client = client
|
|
78
|
+
@api_url = api_url
|
|
79
|
+
@socket_factory = socket_factory || ->(address) { open_socket(address) }
|
|
80
|
+
@reconnect_delay = reconnect_delay || ->(attempt) { default_reconnect_delay(attempt) }
|
|
81
|
+
initialize_realtime_state
|
|
82
|
+
initialize_postgres_database
|
|
83
|
+
end
|
|
76
84
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
)
|
|
94
|
-
type = normalize_channel_type(type)
|
|
95
|
-
batch_config = PostgresBatchConfig.new(
|
|
96
|
-
auto_fetch:, batch_window_ms: fetch_batch_window_ms,
|
|
97
|
-
max_batch_size: fetch_max_batch_size
|
|
85
|
+
def initialize_realtime_state
|
|
86
|
+
@protocol = nil
|
|
87
|
+
@protocol_lock = nil
|
|
88
|
+
@channel_lock = nil
|
|
89
|
+
@channels = {}
|
|
90
|
+
@connection_callbacks = { connect: {}, disconnect: {}, error: {} }
|
|
91
|
+
@next_connection_callback_id = 0
|
|
92
|
+
@protocol_session_lineage = nil
|
|
93
|
+
@reconnect_task = nil
|
|
94
|
+
@closed = false
|
|
95
|
+
end
|
|
96
|
+
private :initialize_realtime_state
|
|
97
|
+
|
|
98
|
+
def channel(
|
|
99
|
+
name, type: :broadcast, auto_fetch: true,
|
|
100
|
+
fetch_batch_window_ms: 20, fetch_max_batch_size: 50
|
|
98
101
|
)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
type = normalize_channel_type(type)
|
|
103
|
+
batch_config = PostgresBatchConfig.new(
|
|
104
|
+
auto_fetch:, batch_window_ms: fetch_batch_window_ms,
|
|
105
|
+
max_batch_size: fetch_max_batch_size
|
|
106
|
+
)
|
|
107
|
+
channel_lock.acquire do
|
|
108
|
+
ensure_open!
|
|
109
|
+
channel_name = "#{type}:#{name}"
|
|
110
|
+
channel = @channels[channel_name]
|
|
111
|
+
next cached_channel(channel, batch_config) if channel
|
|
104
112
|
|
|
105
|
-
|
|
113
|
+
@channels[channel_name] = build_channel(channel_name, type, batch_config)
|
|
114
|
+
end
|
|
106
115
|
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def protocol
|
|
110
|
-
ensure_open!
|
|
111
|
-
return @protocol if @protocol
|
|
112
116
|
|
|
113
|
-
|
|
117
|
+
def protocol
|
|
114
118
|
ensure_open!
|
|
115
|
-
@protocol
|
|
119
|
+
current_protocol = @protocol
|
|
120
|
+
return current_protocol if current_protocol
|
|
121
|
+
|
|
122
|
+
protocol_lock.acquire do
|
|
123
|
+
ensure_open!
|
|
124
|
+
@protocol ||= connect_protocol
|
|
125
|
+
end
|
|
126
|
+
rescue StandardError => e
|
|
127
|
+
raise public_error(e), cause: nil
|
|
116
128
|
end
|
|
117
|
-
|
|
118
|
-
raise public_error(e), cause: nil
|
|
119
|
-
end
|
|
120
|
-
private :protocol
|
|
129
|
+
private :protocol
|
|
121
130
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
131
|
+
def disconnect
|
|
132
|
+
lock = @protocol_lock
|
|
133
|
+
lock ? lock.acquire { close_protocol } : close_protocol
|
|
134
|
+
rescue StandardError => e
|
|
135
|
+
raise public_error(e), cause: nil
|
|
136
|
+
end
|
|
127
137
|
|
|
128
|
-
|
|
129
|
-
|
|
138
|
+
def ensure_open!
|
|
139
|
+
raise ClosedError, 'realtime connection closed' if @closed
|
|
130
140
|
|
|
131
|
-
|
|
132
|
-
|
|
141
|
+
self
|
|
142
|
+
end
|
|
133
143
|
|
|
134
|
-
|
|
144
|
+
private
|
|
135
145
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
146
|
+
def normalize_channel_type(type)
|
|
147
|
+
normalized = type.to_s.to_sym
|
|
148
|
+
return normalized if CHANNEL_TYPES.include?(normalized)
|
|
139
149
|
|
|
140
|
-
|
|
141
|
-
|
|
150
|
+
raise ArgumentError, "unsupported realtime channel type: #{type}"
|
|
151
|
+
end
|
|
142
152
|
|
|
143
|
-
|
|
153
|
+
def report_channel_error(error) = protocol_error(public_error(error))
|
|
144
154
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
155
|
+
def cached_channel(channel, batch_config)
|
|
156
|
+
channel.__send__(:ensure_fetch_config!, batch_config)
|
|
157
|
+
channel
|
|
158
|
+
end
|
|
149
159
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
160
|
+
def build_channel(name, type, batch_config)
|
|
161
|
+
Channel.new(self, -> { protocol }, name, type, batch_config:)
|
|
162
|
+
end
|
|
153
163
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
164
|
+
def protocol_lock
|
|
165
|
+
require 'async/semaphore'
|
|
166
|
+
@protocol_lock ||= Async::Semaphore.new(1)
|
|
167
|
+
end
|
|
158
168
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
169
|
+
def channel_lock
|
|
170
|
+
require 'async/semaphore'
|
|
171
|
+
@channel_lock ||= Async::Semaphore.new(1)
|
|
172
|
+
end
|
|
162
173
|
end
|
|
174
|
+
include Core
|
|
175
|
+
|
|
176
|
+
private_constant :Core
|
|
163
177
|
|
|
164
178
|
# Represents one realtime broadcast channel.
|
|
165
179
|
class Channel
|
|
@@ -175,14 +189,15 @@ module Volcano
|
|
|
175
189
|
|
|
176
190
|
attr_reader :name
|
|
177
191
|
|
|
192
|
+
# @dynamic name
|
|
193
|
+
|
|
178
194
|
def initialize(realtime, protocol_provider, name, type, batch_config:)
|
|
179
195
|
@realtime = realtime
|
|
180
196
|
@protocol_provider = protocol_provider
|
|
181
197
|
@name = name.freeze
|
|
182
198
|
@handler_registered = @subscribed = @subscription_desired = @closed = false
|
|
183
199
|
@lifecycle_lock = nil
|
|
184
|
-
|
|
185
|
-
@recovery_lineage = nil
|
|
200
|
+
initialize_recovery_state
|
|
186
201
|
initialize_callback_dispatch
|
|
187
202
|
initialize_presence(type)
|
|
188
203
|
initialize_postgres_delivery(batch_config)
|
|
@@ -208,7 +223,7 @@ module Volcano
|
|
|
208
223
|
|
|
209
224
|
def unsubscribe
|
|
210
225
|
state = with_lifecycle_lock { unsubscribe_protocol }
|
|
211
|
-
emit_presence_sync(state)
|
|
226
|
+
emit_presence_sync(state) if state.is_a?(Hash)
|
|
212
227
|
nil
|
|
213
228
|
end
|
|
214
229
|
|
|
@@ -218,11 +233,12 @@ module Volcano
|
|
|
218
233
|
|
|
219
234
|
def restore_subscription(protocol)
|
|
220
235
|
state = with_lifecycle_lock do
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
236
|
+
restoration_needed? ? subscribe_protocol(protocol) : nil
|
|
237
|
+
end
|
|
238
|
+
if state
|
|
239
|
+
subscribed_protocol, epoch = state
|
|
240
|
+
sync_presence(subscribed_protocol, epoch)
|
|
224
241
|
end
|
|
225
|
-
sync_presence(*state) if state
|
|
226
242
|
nil
|
|
227
243
|
end
|
|
228
244
|
|
|
@@ -240,6 +256,13 @@ module Volcano
|
|
|
240
256
|
|
|
241
257
|
private
|
|
242
258
|
|
|
259
|
+
def initialize_recovery_state
|
|
260
|
+
# @type var recovery_position: Hash[Symbol, String | Integer]
|
|
261
|
+
recovery_position = {}
|
|
262
|
+
@recovery_position = recovery_position.freeze
|
|
263
|
+
@recovery_lineage = nil
|
|
264
|
+
end
|
|
265
|
+
|
|
243
266
|
def subscribe_with_intent
|
|
244
267
|
ensure_open!
|
|
245
268
|
raise DuplicateSubscriptionError, "already subscribed to #{@name}" if @subscription_desired
|
|
@@ -254,8 +277,8 @@ module Volcano
|
|
|
254
277
|
|
|
255
278
|
def with_lifecycle_lock(&)
|
|
256
279
|
require 'async/semaphore'
|
|
257
|
-
@lifecycle_lock ||= Async::Semaphore.new(1)
|
|
258
|
-
|
|
280
|
+
lock = @lifecycle_lock ||= Async::Semaphore.new(1)
|
|
281
|
+
lock.acquire(&)
|
|
259
282
|
end
|
|
260
283
|
|
|
261
284
|
def ensure_open!
|
data/lib/volcano/session.rb
CHANGED
|
@@ -10,15 +10,26 @@ module Volcano
|
|
|
10
10
|
private_constant :SESSION_USER_CODER
|
|
11
11
|
|
|
12
12
|
# Local credentials; refresh credentials and user identity may be unknown.
|
|
13
|
-
Session = Data.define(:access_token, :refresh_token, :user_id, :user)
|
|
13
|
+
Session = Data.define(:access_token, :refresh_token, :user_id, :user)
|
|
14
|
+
|
|
15
|
+
# Reopens the generated record for checked initialization.
|
|
16
|
+
class Session
|
|
17
|
+
# @dynamic access_token, refresh_token, user_id, user, members, with, to_h
|
|
18
|
+
# @dynamic deconstruct, deconstruct_keys, self.[], self.members
|
|
14
19
|
def initialize(access_token:, refresh_token: nil, user_id: nil, user: nil)
|
|
15
|
-
|
|
20
|
+
user = immutable_user(user)
|
|
21
|
+
super
|
|
16
22
|
end
|
|
17
23
|
|
|
18
24
|
private
|
|
19
25
|
|
|
20
26
|
def immutable_user(value)
|
|
21
|
-
|
|
27
|
+
return if value.nil?
|
|
28
|
+
|
|
29
|
+
snapshot = SESSION_USER_CODER.load(SESSION_USER_CODER.dump(value))
|
|
30
|
+
raise TypeError, 'Session user snapshot must be a Hash' unless snapshot.is_a?(Hash)
|
|
31
|
+
|
|
32
|
+
snapshot
|
|
22
33
|
rescue JSON::GeneratorError, JSON::NestingError
|
|
23
34
|
raise TypeError, 'Session user snapshot must contain JSON values or timestamps', cause: nil
|
|
24
35
|
end
|
data/lib/volcano/transport.rb
CHANGED
|
@@ -20,21 +20,20 @@ module Volcano
|
|
|
20
20
|
|
|
21
21
|
NETWORK_ERRORS = [IOError, SystemCallError, SocketError, Timeout::Error].freeze
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def invoke
|
|
23
|
+
def self.invoke
|
|
26
24
|
yield
|
|
27
|
-
rescue
|
|
25
|
+
rescue IOError, SystemCallError, SocketError, Timeout::Error => e
|
|
28
26
|
raise Error::TransportError, e.message, cause: e
|
|
29
27
|
end
|
|
30
28
|
|
|
31
|
-
def body(response, expected_status)
|
|
29
|
+
def self.body(response, expected_status)
|
|
32
30
|
return response.body if response.status == expected_status
|
|
33
31
|
|
|
34
32
|
raise response_error(response)
|
|
35
33
|
end
|
|
36
34
|
|
|
37
|
-
def response_error(response)
|
|
35
|
+
def self.response_error(response)
|
|
36
|
+
# @type var payload: Hash[String, Object?]
|
|
38
37
|
payload = response.body.is_a?(Hash) ? response.body : {}
|
|
39
38
|
retry_after = integer_header(response.headers, 'Retry-After') if response.status == 429
|
|
40
39
|
error_type(response.status).new(
|
|
@@ -45,20 +44,63 @@ module Volcano
|
|
|
45
44
|
)
|
|
46
45
|
end
|
|
47
46
|
|
|
48
|
-
def error_message(payload)
|
|
49
|
-
|
|
47
|
+
def self.error_message(payload)
|
|
48
|
+
error = payload['error']
|
|
49
|
+
return error if error.is_a?(String)
|
|
50
|
+
|
|
51
|
+
message = payload['message']
|
|
52
|
+
message.is_a?(String) ? message : 'Volcano request failed'
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.json_value(value)
|
|
56
|
+
case value
|
|
57
|
+
when Array then value.map { |entry| json_value(entry) }
|
|
58
|
+
when Hash then json_object(value)
|
|
59
|
+
else json_scalar(value)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.json_object(value, message: 'Expected a JSON object')
|
|
64
|
+
raise TypeError, message unless value.is_a?(Hash)
|
|
65
|
+
|
|
66
|
+
value.to_h do |key, item|
|
|
67
|
+
raise TypeError, message unless key.is_a?(String)
|
|
68
|
+
|
|
69
|
+
[key, json_value(item)]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def self.json_rows(value)
|
|
74
|
+
rows = json_object(value)['data']
|
|
75
|
+
raise TypeError, 'Expected database rows' unless rows.is_a?(Array)
|
|
76
|
+
|
|
77
|
+
rows.map { |row| json_object(row) }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.finite_float(value)
|
|
81
|
+
raise TypeError, 'Expected a finite JSON number' unless value.finite?
|
|
82
|
+
|
|
83
|
+
value
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.json_scalar(value)
|
|
87
|
+
case value
|
|
88
|
+
when NilClass, TrueClass, FalseClass, Integer, String then value
|
|
89
|
+
when Float then finite_float(value)
|
|
90
|
+
else raise TypeError, 'Expected a JSON response'
|
|
91
|
+
end
|
|
50
92
|
end
|
|
51
93
|
|
|
52
|
-
def error_type(status)
|
|
94
|
+
def self.error_type(status)
|
|
53
95
|
ERROR_TYPES.fetch(status) do
|
|
54
96
|
status.between?(500, 599) ? Error::ServerError : Error::VolcanoError
|
|
55
97
|
end
|
|
56
98
|
end
|
|
57
99
|
|
|
58
|
-
def integer_header(headers, name)
|
|
100
|
+
def self.integer_header(headers, name)
|
|
59
101
|
value = headers&.find { |key, _| key.casecmp?(name) }&.last
|
|
60
102
|
Integer(value, exception: false)
|
|
61
103
|
end
|
|
62
|
-
private_class_method :error_type, :integer_header, :response_error
|
|
104
|
+
private_class_method :error_type, :integer_header, :response_error, :finite_float, :json_scalar
|
|
63
105
|
end
|
|
64
106
|
end
|
data/lib/volcano/user.rb
CHANGED
|
@@ -10,15 +10,20 @@ module Volcano
|
|
|
10
10
|
User = Data.define(
|
|
11
11
|
:id, :project_id, :email, :email_confirmed, :user_metadata, :app_metadata,
|
|
12
12
|
:avatar_url, :status, :banned_until, :last_sign_in_at, :created_at, :updated_at
|
|
13
|
-
)
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
# Reopens the generated record for checked initialization.
|
|
16
|
+
class User
|
|
17
|
+
# @dynamic id, project_id, email, email_confirmed, user_metadata, app_metadata
|
|
18
|
+
# @dynamic avatar_url, status, banned_until, last_sign_in_at, created_at, updated_at
|
|
19
|
+
# @dynamic members, with, to_h, deconstruct, deconstruct_keys, self.[], self.members
|
|
14
20
|
def initialize(id:, email:, status:, **attributes)
|
|
15
21
|
validate_optional_attributes(attributes)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
)
|
|
22
|
+
id = freeze_value(id)
|
|
23
|
+
email = freeze_value(email)
|
|
24
|
+
status = freeze_value(status)
|
|
25
|
+
attributes = USER_OPTIONAL_ATTRIBUTES.to_h { |name| [name, freeze_value(attributes[name])] }
|
|
26
|
+
super
|
|
22
27
|
end
|
|
23
28
|
|
|
24
29
|
private
|
data/lib/volcano/version.rb
CHANGED
data/lib/volcano.rb
CHANGED
|
@@ -16,6 +16,7 @@ require_relative 'volcano/auth_state'
|
|
|
16
16
|
require_relative 'volcano/errors'
|
|
17
17
|
require_relative 'volcano/redaction'
|
|
18
18
|
require_relative 'volcano/transport'
|
|
19
|
+
require_relative 'volcano/immutable_request_value'
|
|
19
20
|
require_relative 'volcano/generated_transport'
|
|
20
21
|
require_relative 'volcano/auth_notification_dispatch'
|
|
21
22
|
require_relative 'volcano/auth_session_binding'
|
|
@@ -20,7 +20,7 @@ module Volcano
|
|
|
20
20
|
| (id: String, user_id: String, provider: String, expires_at: Time, is_active: bool, is_current: bool, ?user_agent: String?, ?ip_address: String?, ?last_ip_address: String?, ?last_activity_at: Time?, ?session_started_at: Time?, ?created_at: Time?, ?updated_at: Time?) -> AuthSession
|
|
21
21
|
def self.members: () -> [:id, :user_id, :provider, :expires_at, :is_active, :is_current, :user_agent, :ip_address, :last_ip_address, :last_activity_at, :session_started_at, :created_at, :updated_at]
|
|
22
22
|
|
|
23
|
-
def initialize: (
|
|
23
|
+
private def initialize: (**Object? attributes) -> void
|
|
24
24
|
def members: () -> [:id, :user_id, :provider, :expires_at, :is_active, :is_current, :user_agent, :ip_address, :last_ip_address, :last_activity_at, :session_started_at, :created_at, :updated_at]
|
|
25
25
|
def with: (?id: String, ?user_id: String, ?provider: String, ?expires_at: Time, ?is_active: bool, ?is_current: bool, ?user_agent: String?, ?ip_address: String?, ?last_ip_address: String?, ?last_activity_at: Time?, ?session_started_at: Time?, ?created_at: Time?, ?updated_at: Time?) -> AuthSession
|
|
26
26
|
def to_h: () -> { id: String, user_id: String, provider: String, expires_at: Time, is_active: bool, is_current: bool, user_agent: String?, ip_address: String?, last_ip_address: String?, last_activity_at: Time?, session_started_at: Time?, created_at: Time?, updated_at: Time? }
|
data/sig/client.rbs
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Volcano
|
|
2
|
+
class Client
|
|
3
|
+
attr_reader auth: Auth
|
|
4
|
+
attr_reader functions: Functions
|
|
5
|
+
attr_reader durable: Durable
|
|
6
|
+
attr_reader logs: Logs
|
|
7
|
+
attr_reader storage: Storage
|
|
8
|
+
attr_reader locks: Locks
|
|
9
|
+
attr_reader realtime: Realtime
|
|
10
|
+
|
|
11
|
+
def initialize: (anon_key: String, ?api_url: String, ?service_key: String?, ?timeout: (Integer | Float), ?access_token: String?, ?refresh_token: String?) -> void
|
|
12
|
+
def current_session: () -> Session?
|
|
13
|
+
def database: (String name) -> Database
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module Volcano
|
|
2
|
+
type sdk_json = nil | bool | Integer | Float | String | Time | Array[sdk_json] | Hash[String | Symbol, sdk_json]
|
|
3
|
+
type sdk_payload = Hash[String | Symbol, sdk_json]
|
|
4
|
+
type database_rows = Array[Hash[String, json_value]]
|
|
5
|
+
|
|
6
|
+
class Database
|
|
7
|
+
def from: (String table) -> QueryBuilder
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class QueryBuilder
|
|
11
|
+
def select: (*String columns) -> QueryBuilder
|
|
12
|
+
def insert: (sdk_payload values) -> InsertBuilder
|
|
13
|
+
def update: (sdk_payload values) -> UpdateBuilder
|
|
14
|
+
def delete: () -> DeleteBuilder
|
|
15
|
+
def order: (String column, ?ascending: bool) -> QueryBuilder
|
|
16
|
+
def limit: (Integer count) -> QueryBuilder
|
|
17
|
+
def offset: (Integer count) -> QueryBuilder
|
|
18
|
+
def execute: () -> database_rows
|
|
19
|
+
|
|
20
|
+
def eq: (String column, sdk_json value) -> QueryBuilder
|
|
21
|
+
def neq: (String column, sdk_json value) -> QueryBuilder
|
|
22
|
+
def gt: (String column, sdk_json value) -> QueryBuilder
|
|
23
|
+
def gte: (String column, sdk_json value) -> QueryBuilder
|
|
24
|
+
def lt: (String column, sdk_json value) -> QueryBuilder
|
|
25
|
+
def lte: (String column, sdk_json value) -> QueryBuilder
|
|
26
|
+
def like: (String column, String pattern) -> QueryBuilder
|
|
27
|
+
def ilike: (String column, String pattern) -> QueryBuilder
|
|
28
|
+
def is: (String column, sdk_json value) -> QueryBuilder
|
|
29
|
+
def in: (String column, Array[sdk_json] values) -> QueryBuilder
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class InsertBuilder
|
|
33
|
+
def execute: () -> database_rows
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class UpdateBuilder
|
|
37
|
+
def execute: () -> database_rows
|
|
38
|
+
|
|
39
|
+
def eq: (String column, sdk_json value) -> UpdateBuilder
|
|
40
|
+
def neq: (String column, sdk_json value) -> UpdateBuilder
|
|
41
|
+
def gt: (String column, sdk_json value) -> UpdateBuilder
|
|
42
|
+
def gte: (String column, sdk_json value) -> UpdateBuilder
|
|
43
|
+
def lt: (String column, sdk_json value) -> UpdateBuilder
|
|
44
|
+
def lte: (String column, sdk_json value) -> UpdateBuilder
|
|
45
|
+
def like: (String column, String pattern) -> UpdateBuilder
|
|
46
|
+
def ilike: (String column, String pattern) -> UpdateBuilder
|
|
47
|
+
def is: (String column, sdk_json value) -> UpdateBuilder
|
|
48
|
+
def in: (String column, Array[sdk_json] values) -> UpdateBuilder
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class DeleteBuilder
|
|
52
|
+
def execute: () -> database_rows
|
|
53
|
+
|
|
54
|
+
def eq: (String column, sdk_json value) -> DeleteBuilder
|
|
55
|
+
def neq: (String column, sdk_json value) -> DeleteBuilder
|
|
56
|
+
def gt: (String column, sdk_json value) -> DeleteBuilder
|
|
57
|
+
def gte: (String column, sdk_json value) -> DeleteBuilder
|
|
58
|
+
def lt: (String column, sdk_json value) -> DeleteBuilder
|
|
59
|
+
def lte: (String column, sdk_json value) -> DeleteBuilder
|
|
60
|
+
def like: (String column, String pattern) -> DeleteBuilder
|
|
61
|
+
def ilike: (String column, String pattern) -> DeleteBuilder
|
|
62
|
+
def is: (String column, sdk_json value) -> DeleteBuilder
|
|
63
|
+
def in: (String column, Array[sdk_json] values) -> DeleteBuilder
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class Functions
|
|
67
|
+
def invoke: (String name, ?sdk_payload payload) -> FunctionResponse
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class Durable
|
|
71
|
+
def start: (String function_name, ?sdk_payload payload, ?execution_name: String?) -> DurableExecution
|
|
72
|
+
def get: (String project_id, String function_name, String execution_id) -> DurableExecution
|
|
73
|
+
def list: (String project_id, String function_name, ?status: String?, ?page: Integer?, ?limit: Integer?) -> DurableExecutionPage
|
|
74
|
+
def stop: (String project_id, String function_name, String execution_id) -> DurableExecution
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class Logs
|
|
78
|
+
def search: (String project_id, sdk_payload request) -> LogSearchResponse
|
|
79
|
+
def activity: (String project_id, sdk_payload request) -> LogActivityResponse
|
|
80
|
+
end
|
|
81
|
+
end
|
data/sig/durable_records.rbs
CHANGED
|
@@ -36,7 +36,7 @@ module Volcano
|
|
|
36
36
|
| (id: String, function_id: String, name: String, status: String, region: String, created_at: Time, ?result: json_value, ?result_expired: bool?, ?error: DurableExecutionError?, ?completed_at: Time?) -> DurableExecution
|
|
37
37
|
def self.members: () -> [:id, :function_id, :name, :status, :region, :created_at, :result, :result_expired, :error, :completed_at]
|
|
38
38
|
|
|
39
|
-
def initialize: (
|
|
39
|
+
private def initialize: (**(json_value | Time | DurableExecutionError) attributes) -> void
|
|
40
40
|
def members: () -> [:id, :function_id, :name, :status, :region, :created_at, :result, :result_expired, :error, :completed_at]
|
|
41
41
|
def with: (?id: String, ?function_id: String, ?name: String, ?status: String, ?region: String, ?created_at: Time, ?result: json_value, ?result_expired: bool?, ?error: DurableExecutionError?, ?completed_at: Time?) -> DurableExecution
|
|
42
42
|
def to_h: () -> { id: String, function_id: String, name: String, status: String, region: String, created_at: Time, result: json_value, result_expired: bool?, error: DurableExecutionError?, completed_at: Time? }
|
data/sig/locks.rbs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module Volcano
|
|
2
|
+
class Locks
|
|
3
|
+
def get: (String key, ?request_id: String?) -> LockState
|
|
4
|
+
def acquire: (String key, ttl: Integer, ?token: String?, ?request_id: String?) -> LockLease
|
|
5
|
+
def renew: (String key, LockLease lease, ttl: Integer, ?request_id: String?) -> LockLease
|
|
6
|
+
def release: (String key, LockLease lease, ?request_id: String?) -> nil
|
|
7
|
+
def force_release: (String key, ?request_id: String?) -> nil
|
|
8
|
+
def with_lock: [T] (String key, ttl: Integer, ?token: String?, ?request_id: String?) { (LockGuard) -> T } -> T
|
|
9
|
+
end
|
|
10
|
+
end
|
data/sig/realtime.rbs
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Volcano
|
|
2
|
+
class Realtime
|
|
3
|
+
def channel: (String name, ?type: String | Symbol, ?auto_fetch: bool, ?fetch_batch_window_ms: Integer, ?fetch_max_batch_size: Integer) -> Channel
|
|
4
|
+
def connected?: () -> bool
|
|
5
|
+
def disconnect: () -> void
|
|
6
|
+
def remove_channel: (String name, ?type: String | Symbol) -> nil
|
|
7
|
+
def remove_all_channels: () -> nil
|
|
8
|
+
|
|
9
|
+
def on_connect: (^(ConnectContext) -> void callback) -> ^() -> Proc?
|
|
10
|
+
| () { (ConnectContext) -> void } -> ^() -> Proc?
|
|
11
|
+
def on_disconnect: (^(DisconnectContext) -> void callback) -> ^() -> Proc?
|
|
12
|
+
| () { (DisconnectContext) -> void } -> ^() -> Proc?
|
|
13
|
+
def on_error: (^(ErrorContext) -> void callback) -> ^() -> Proc?
|
|
14
|
+
| () { (ErrorContext) -> void } -> ^() -> Proc?
|
|
15
|
+
|
|
16
|
+
def database_name: () -> String?
|
|
17
|
+
def database_name=: (String? name) -> String?
|
|
18
|
+
|
|
19
|
+
class Channel
|
|
20
|
+
attr_reader name: String
|
|
21
|
+
|
|
22
|
+
def subscribe: () -> nil
|
|
23
|
+
def unsubscribe: () -> nil
|
|
24
|
+
def send: (event: String | Symbol, **json_value payload) -> nil
|
|
25
|
+
|
|
26
|
+
def on: ("message" event, ^(Hash[String, json_value]) -> void callback) -> self
|
|
27
|
+
| ("message" event) { (Hash[String, json_value]) -> void } -> self
|
|
28
|
+
| ("join" | "leave" event, ^(PresenceInfo) -> void callback) -> self
|
|
29
|
+
| ("join" | "leave" event) { (PresenceInfo) -> void } -> self
|
|
30
|
+
| ("presence_sync" event, ^(Hash[String, PresenceInfo]) -> void callback) -> self
|
|
31
|
+
| ("presence_sync" event) { (Hash[String, PresenceInfo]) -> void } -> self
|
|
32
|
+
| ("INSERT" | "UPDATE" | "DELETE" | "*" event, ^(PostgresChange) -> void callback) -> self
|
|
33
|
+
| ("INSERT" | "UPDATE" | "DELETE" | "*" event) { (PostgresChange) -> void } -> self
|
|
34
|
+
def on_presence_sync: (^(Hash[String, PresenceInfo]) -> void callback) -> self
|
|
35
|
+
| () { (Hash[String, PresenceInfo]) -> void } -> self
|
|
36
|
+
def on_postgres_changes: (String | Symbol event, schema: String, table: String, callback: ^(PostgresChange) -> void) -> self
|
|
37
|
+
| (String | Symbol event, schema: String, table: String) { (PostgresChange) -> void } -> self
|
|
38
|
+
|
|
39
|
+
def track: (?Hash[String, json_value] state) -> nil
|
|
40
|
+
def presence_state: () -> Hash[String, PresenceInfo]
|
|
41
|
+
def get_presence_state: () -> Hash[String, PresenceInfo]
|
|
42
|
+
def tracked_state: () -> Hash[String, json_value]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|