volcano-sdk 0.27.0 → 0.29.0
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/lib/volcano/function_resolution.rb +18 -15
- data/lib/volcano/function_response.rb +8 -7
- data/lib/volcano/functions.rb +1 -1
- data/lib/volcano/generated_transport.rb +6 -3
- data/lib/volcano/lock_guard.rb +6 -2
- data/lib/volcano/lock_renewer.rb +3 -2
- data/lib/volcano/lock_response.rb +48 -0
- data/lib/volcano/lock_session.rb +1 -0
- data/lib/volcano/locks.rb +57 -33
- data/lib/volcano/log_responses.rb +11 -7
- data/lib/volcano/realtime/blocking_call.rb +8 -9
- data/lib/volcano/realtime/protocol_recovery_position.rb +10 -5
- data/lib/volcano/sign_up_result.rb +6 -1
- data/lib/volcano/version.rb +1 -1
- data/lib/volcano.rb +2 -1
- data/sig/lock_guard.rbs +21 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e946d4476603cf2c234194f51e63aadd8ca1327719bcae02bf098de61049b65b
|
|
4
|
+
data.tar.gz: 38d3aa7dbbc508796620f75285b2a483b70a9e2d49a255aded0dba3fa023334b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 014b16629b5d06e89d39f010b1c8cb550582f3f7f224b6c6911324c6b2b07196eed9729305c2edd623d6fbedb2ba12a9460d4d128bda61202c9c88874823fada
|
|
7
|
+
data.tar.gz: d98691e237fd5cdb277f701701e3549aa6e533179d36c0039e188a66143fe5992a1ac9565f210304704838d2e855a9512e9e2e60de7ec0b2abfa9a8a30ae4cb2
|
|
@@ -16,11 +16,7 @@ module Volcano
|
|
|
16
16
|
# A cached resolve result. A nil resolution is a remembered miss.
|
|
17
17
|
Outcome = Data.define(:resolution, :failure)
|
|
18
18
|
|
|
19
|
-
Failure = Data.define(:message, :code, :retry_after)
|
|
20
|
-
def exception
|
|
21
|
-
Error::NotFoundError.new(message.dup, status: 404, code: code&.dup, retry_after: retry_after)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
19
|
+
Failure = Data.define(:message, :code, :retry_after)
|
|
24
20
|
private_constant :Failure
|
|
25
21
|
|
|
26
22
|
Entry = Data.define(:outcome, :expires_at)
|
|
@@ -51,21 +47,23 @@ module Volcano
|
|
|
51
47
|
# when the API itself is plaintext, so a resolve response cannot
|
|
52
48
|
# downgrade a credential that is otherwise protected in transit.
|
|
53
49
|
def valid_invoke_url(value, api_url)
|
|
54
|
-
|
|
50
|
+
url = nonempty_url(value)
|
|
51
|
+
return nil unless url
|
|
55
52
|
|
|
56
|
-
uri = URI.parse(
|
|
53
|
+
uri = URI.parse(url)
|
|
57
54
|
return nil unless usable_address?(uri)
|
|
58
55
|
|
|
59
|
-
usable_scheme?(uri.scheme, api_url) ?
|
|
56
|
+
usable_scheme?(uri.scheme, api_url) ? url : nil
|
|
60
57
|
rescue URI::InvalidURIError
|
|
61
58
|
nil
|
|
62
59
|
end
|
|
63
60
|
|
|
64
61
|
# Returns the cached Outcome for a name, or nil when it must be resolved.
|
|
65
62
|
def lookup(api_url, authorization, name)
|
|
63
|
+
# @type var key: [String, String, String]
|
|
66
64
|
key = [api_url, authorization, name]
|
|
67
65
|
@lock.synchronize do
|
|
68
|
-
entry = @entries
|
|
66
|
+
entry = @entries.fetch(key, nil)
|
|
69
67
|
next nil if entry.nil?
|
|
70
68
|
|
|
71
69
|
if entry.expires_at <= now
|
|
@@ -89,6 +87,11 @@ module Volcano
|
|
|
89
87
|
write([api_url, authorization, name], Outcome.new(resolution: nil, failure: failure), NEGATIVE_TTL_SECONDS)
|
|
90
88
|
end
|
|
91
89
|
|
|
90
|
+
def error_for(failure)
|
|
91
|
+
Error::NotFoundError.new(failure.message.dup, status: 404, code: failure.code&.dup,
|
|
92
|
+
retry_after: failure.retry_after)
|
|
93
|
+
end
|
|
94
|
+
|
|
92
95
|
# Drops one cached resolution that turned out to be stale.
|
|
93
96
|
def forget(api_url, authorization, name)
|
|
94
97
|
@lock.synchronize { @entries.delete([api_url, authorization, name]) }
|
|
@@ -106,8 +109,8 @@ module Volcano
|
|
|
106
109
|
|
|
107
110
|
private
|
|
108
111
|
|
|
109
|
-
def nonempty_url
|
|
110
|
-
value.is_a?(String) && !value.empty?
|
|
112
|
+
def nonempty_url(value)
|
|
113
|
+
value if value.is_a?(String) && !value.empty?
|
|
111
114
|
end
|
|
112
115
|
|
|
113
116
|
def usable_address?(uri)
|
|
@@ -126,15 +129,15 @@ module Volcano
|
|
|
126
129
|
def write(key, outcome, ttl_seconds)
|
|
127
130
|
@lock.synchronize do
|
|
128
131
|
@entries[key] = Entry.new(outcome: outcome, expires_at: now + ttl_seconds)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
evict_expired_entries
|
|
132
|
+
evict_expired_entries if @entries.size > MAX_ENTRIES
|
|
132
133
|
end
|
|
133
134
|
end
|
|
134
135
|
|
|
135
136
|
def evict_expired_entries
|
|
136
137
|
@entries.delete_if { |_, entry| entry.expires_at <= now }
|
|
137
|
-
|
|
138
|
+
while @entries.size > MAX_ENTRIES
|
|
139
|
+
@entries.min_by(1) { |_, entry| entry.expires_at }.each { |pair| @entries.delete(pair.first) }
|
|
140
|
+
end
|
|
138
141
|
end
|
|
139
142
|
end
|
|
140
143
|
end
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module Volcano
|
|
4
4
|
# Immutable result of one function invocation.
|
|
5
|
-
FunctionResponse = Data.define(:data, :status, :headers, :version)
|
|
5
|
+
FunctionResponse = Data.define(:data, :status, :headers, :version)
|
|
6
|
+
|
|
7
|
+
# Reopen the generated Data class so Steep can check its initializer.
|
|
8
|
+
class FunctionResponse
|
|
6
9
|
def initialize(data:, status:, headers:, version:)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
version: version&.dup&.freeze
|
|
12
|
-
)
|
|
10
|
+
data = immutable_json(data)
|
|
11
|
+
headers = immutable_json(headers)
|
|
12
|
+
version = version&.dup&.freeze
|
|
13
|
+
super
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
private
|
data/lib/volcano/functions.rb
CHANGED
|
@@ -52,7 +52,9 @@ module Volcano
|
|
|
52
52
|
invoke do
|
|
53
53
|
apis = @api_factory.call(authorization)
|
|
54
54
|
body = Generated::ProjectLockLeaseRequest.new(ttl_seconds: ttl)
|
|
55
|
-
result = apis.locks.acquire_project_lock_with_http_info(
|
|
55
|
+
result = apis.locks.acquire_project_lock_with_http_info(
|
|
56
|
+
key, token, request_id, body, debug_return_type: 'Object'
|
|
57
|
+
)
|
|
56
58
|
data, status, headers = result
|
|
57
59
|
response(data, status, headers)
|
|
58
60
|
end
|
|
@@ -63,7 +65,8 @@ module Volcano
|
|
|
63
65
|
apis = @api_factory.call(authorization)
|
|
64
66
|
data, status, headers = apis.locks.get_project_lock_with_http_info(
|
|
65
67
|
key,
|
|
66
|
-
request_id
|
|
68
|
+
request_id,
|
|
69
|
+
debug_return_type: 'Object'
|
|
67
70
|
)
|
|
68
71
|
response(data, status, headers)
|
|
69
72
|
end
|
|
@@ -85,7 +88,7 @@ module Volcano
|
|
|
85
88
|
apis = @api_factory.call(authorization)
|
|
86
89
|
body = Generated::ProjectLockLeaseRequest.new(ttl_seconds: ttl)
|
|
87
90
|
result = apis.locks.renew_project_lock_with_http_info(
|
|
88
|
-
key, token, request_id, body
|
|
91
|
+
key, token, request_id, body, debug_return_type: 'Object'
|
|
89
92
|
)
|
|
90
93
|
data, status, headers = result
|
|
91
94
|
response(data, status, headers)
|
data/lib/volcano/lock_guard.rb
CHANGED
|
@@ -84,7 +84,7 @@ module Volcano
|
|
|
84
84
|
wait = wait_duration(deadline)
|
|
85
85
|
return false unless wait
|
|
86
86
|
|
|
87
|
-
@changed.wait(@mutex, wait)
|
|
87
|
+
@changed.wait(@mutex, Float(wait))
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
90
|
|
|
@@ -129,7 +129,11 @@ module Volcano
|
|
|
129
129
|
def remaining_time = @lease_clock.remaining
|
|
130
130
|
|
|
131
131
|
def wait_deadline(timeout)
|
|
132
|
-
|
|
132
|
+
return unless timeout
|
|
133
|
+
|
|
134
|
+
raise ArgumentError, 'invalid timeout' unless timeout.is_a?(Numeric) && timeout.real? && timeout.finite?
|
|
135
|
+
|
|
136
|
+
@lease_clock.monotonic_now + timeout
|
|
133
137
|
end
|
|
134
138
|
end
|
|
135
139
|
end
|
data/lib/volcano/lock_renewer.rb
CHANGED
|
@@ -22,10 +22,11 @@ module Volcano
|
|
|
22
22
|
|
|
23
23
|
def stop
|
|
24
24
|
request_stop
|
|
25
|
-
|
|
25
|
+
thread = @thread
|
|
26
|
+
return unless thread
|
|
26
27
|
|
|
27
28
|
# Renew requires current token ownership, so a late request cannot resurrect a released lease.
|
|
28
|
-
|
|
29
|
+
thread.join(@config.shutdown_timeout)
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
private
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'time'
|
|
4
|
+
|
|
5
|
+
module Volcano
|
|
6
|
+
# Validates lock response fields before creating public records.
|
|
7
|
+
module LockResponse
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def parse_time(value)
|
|
11
|
+
return Time.iso8601(value) if value.is_a?(String)
|
|
12
|
+
return value if value.nil? || value.is_a?(Time)
|
|
13
|
+
|
|
14
|
+
raise Error::TransportError, 'invalid lock expiry'
|
|
15
|
+
rescue ArgumentError => e
|
|
16
|
+
raise Error::TransportError, 'invalid lock expiry', cause: e
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def required_time(value)
|
|
20
|
+
parse_time(value) || raise(Error::TransportError, 'invalid lock expiry')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def lock_payload(body)
|
|
24
|
+
raise Error::TransportError, 'invalid lock response' unless body.is_a?(Hash)
|
|
25
|
+
|
|
26
|
+
body
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def lock_held(value)
|
|
30
|
+
return true if value == true
|
|
31
|
+
return false if value == false
|
|
32
|
+
|
|
33
|
+
raise Error::TransportError, 'invalid lock held flag'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def required_fencing_token(value)
|
|
37
|
+
raise Error::TransportError, 'invalid lock fencing token' unless value.is_a?(Integer)
|
|
38
|
+
|
|
39
|
+
value
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def optional_fencing_token(value)
|
|
43
|
+
return if value.nil?
|
|
44
|
+
|
|
45
|
+
required_fencing_token(value)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/volcano/lock_session.rb
CHANGED
data/lib/volcano/locks.rb
CHANGED
|
@@ -7,6 +7,7 @@ module Volcano
|
|
|
7
7
|
# Acquires and releases project-scoped distributed locks.
|
|
8
8
|
class Locks
|
|
9
9
|
include LockAutoRenewal
|
|
10
|
+
include LockResponse
|
|
10
11
|
|
|
11
12
|
def initialize(client, transport)
|
|
12
13
|
@client = client
|
|
@@ -14,80 +15,103 @@ module Volcano
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def get(key, request_id: nil)
|
|
17
|
-
payload =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
)
|
|
18
|
+
payload = lock_payload(perform_request(200) do
|
|
19
|
+
@transport.get_project_lock(
|
|
20
|
+
authorization: @client.service_token, key: key, request_id: request_uuid(request_id, 'request_id')
|
|
21
|
+
)
|
|
22
|
+
end)
|
|
23
|
+
build_state(payload)
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
def acquire(key, ttl:, token: nil, request_id: nil)
|
|
26
27
|
validate_ttl(ttl)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
payload = acquire_payload(
|
|
32
|
-
|
|
28
|
+
authorization = @client.service_token.dup.freeze
|
|
29
|
+
owned_key = key.dup.freeze
|
|
30
|
+
owned_token = request_uuid(token, 'token')
|
|
31
|
+
owned_request_id = request_uuid(request_id, 'request_id')
|
|
32
|
+
payload = acquire_payload(
|
|
33
|
+
authorization: authorization, key: owned_key, ttl: ttl, token: owned_token, request_id: owned_request_id
|
|
34
|
+
)
|
|
35
|
+
build_lease(owned_key, owned_token, payload)
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
def renew(key, lease, ttl:, request_id: nil)
|
|
36
39
|
validate_ttl(ttl)
|
|
37
|
-
payload =
|
|
38
|
-
|
|
40
|
+
payload = lock_payload(perform_request(200) do
|
|
41
|
+
@transport.renew_project_lock(
|
|
42
|
+
authorization: @client.service_token, key: key, ttl: ttl,
|
|
43
|
+
token: lease.token, request_id: request_uuid(request_id, 'request_id')
|
|
44
|
+
)
|
|
45
|
+
end)
|
|
39
46
|
build_lease(key, lease.token, payload)
|
|
40
47
|
end
|
|
41
48
|
|
|
42
49
|
def release(key, lease, request_id: nil)
|
|
43
|
-
|
|
50
|
+
perform_request(204) do
|
|
51
|
+
@transport.release_project_lock(
|
|
52
|
+
authorization: @client.service_token, key: key, token: lease.token,
|
|
53
|
+
request_id: request_uuid(request_id, 'request_id')
|
|
54
|
+
)
|
|
55
|
+
end
|
|
44
56
|
nil
|
|
45
57
|
end
|
|
46
58
|
|
|
47
59
|
def force_release(key, request_id: nil)
|
|
48
|
-
|
|
60
|
+
perform_request(204) do
|
|
61
|
+
@transport.force_release_project_lock(
|
|
62
|
+
authorization: @client.service_token, key: key, request_id: request_uuid(request_id, 'request_id')
|
|
63
|
+
)
|
|
64
|
+
end
|
|
49
65
|
nil
|
|
50
66
|
end
|
|
51
67
|
|
|
52
68
|
private
|
|
53
69
|
|
|
54
|
-
def acquire_payload(
|
|
55
|
-
perform_request(
|
|
70
|
+
def acquire_payload(authorization:, key:, ttl:, token:, request_id:)
|
|
71
|
+
lock_payload(perform_request(201) do
|
|
72
|
+
@transport.acquire_project_lock(authorization: authorization, key: key, ttl: ttl,
|
|
73
|
+
token: token, request_id: request_id)
|
|
74
|
+
end)
|
|
56
75
|
rescue Error::TransportError, Error::ServerError => e
|
|
57
76
|
raise unless e.status.nil? || e.status == 503
|
|
58
77
|
|
|
59
|
-
perform_request(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
parameters[:authorization] = @client.service_token
|
|
64
|
-
parameters[:request_id] = request_uuid(parameters[:request_id], 'request_id')
|
|
65
|
-
perform_request(operation, status, parameters)
|
|
78
|
+
lock_payload(perform_request(201) do
|
|
79
|
+
@transport.acquire_project_lock(authorization: authorization, key: key, ttl: ttl,
|
|
80
|
+
token: token, request_id: request_id)
|
|
81
|
+
end)
|
|
66
82
|
end
|
|
67
83
|
|
|
68
|
-
def perform_request(
|
|
69
|
-
response = Transport.invoke
|
|
84
|
+
def perform_request(status, &)
|
|
85
|
+
response = Transport.invoke(&)
|
|
70
86
|
Transport.body(response, status)
|
|
71
87
|
end
|
|
72
88
|
|
|
73
89
|
def request_uuid(value, name)
|
|
74
90
|
return SecureRandom.uuid.freeze if value.nil?
|
|
75
91
|
|
|
76
|
-
|
|
77
|
-
|
|
92
|
+
unless value.is_a?(String) && value.match?(/\A[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}\z/i)
|
|
93
|
+
raise ArgumentError, "#{name} must be a UUID string"
|
|
94
|
+
end
|
|
78
95
|
|
|
79
96
|
value.dup.freeze
|
|
80
97
|
end
|
|
81
98
|
|
|
82
99
|
def build_lease(key, token, payload)
|
|
83
100
|
LockLease.new(
|
|
84
|
-
key: key, token: token, expires_at:
|
|
85
|
-
fencing_token: payload['fencing_token']
|
|
101
|
+
key: key, token: token, expires_at: required_time(payload['expires_at']),
|
|
102
|
+
fencing_token: required_fencing_token(payload['fencing_token'])
|
|
86
103
|
)
|
|
87
104
|
end
|
|
88
105
|
|
|
89
|
-
def
|
|
90
|
-
|
|
106
|
+
def build_state(payload)
|
|
107
|
+
held = lock_held(payload['held'])
|
|
108
|
+
expiry = held ? required_time(payload['expires_at']) : parse_time(payload['expires_at'])
|
|
109
|
+
fencing = if held
|
|
110
|
+
required_fencing_token(payload['fencing_token'])
|
|
111
|
+
else
|
|
112
|
+
optional_fencing_token(payload['fencing_token'])
|
|
113
|
+
end
|
|
114
|
+
LockState.new(held: held, expires_at: expiry, fencing_token: fencing)
|
|
91
115
|
end
|
|
92
116
|
end
|
|
93
117
|
end
|
|
@@ -20,24 +20,28 @@ module Volcano
|
|
|
20
20
|
end
|
|
21
21
|
private_constant :ImmutableLogJSON
|
|
22
22
|
|
|
23
|
+
LogSearchResponse = Data.define(:data, :limit, :has_more, :next_cursor)
|
|
24
|
+
|
|
23
25
|
# Immutable page returned by a project log search.
|
|
24
|
-
LogSearchResponse
|
|
26
|
+
class LogSearchResponse
|
|
25
27
|
include ImmutableLogJSON
|
|
26
28
|
|
|
27
29
|
def initialize(data:, limit:, has_more:, next_cursor: nil)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
30
|
+
data = immutable_json(data)
|
|
31
|
+
next_cursor = next_cursor&.dup&.freeze
|
|
32
|
+
super
|
|
32
33
|
end
|
|
33
34
|
end
|
|
34
35
|
|
|
36
|
+
LogActivityResponse = Data.define(:data, :total)
|
|
37
|
+
|
|
35
38
|
# Immutable bucketed project log activity.
|
|
36
|
-
LogActivityResponse
|
|
39
|
+
class LogActivityResponse
|
|
37
40
|
include ImmutableLogJSON
|
|
38
41
|
|
|
39
42
|
def initialize(data:, total:)
|
|
40
|
-
|
|
43
|
+
data = immutable_json(data)
|
|
44
|
+
super
|
|
41
45
|
end
|
|
42
46
|
end
|
|
43
47
|
end
|
|
@@ -4,26 +4,25 @@ module Volcano
|
|
|
4
4
|
class Realtime
|
|
5
5
|
# Runs one blocking operation off the Async reactor and returns its result.
|
|
6
6
|
module BlockingCall
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
Success = Data.define(:value)
|
|
8
|
+
Failure = Data.define(:error)
|
|
9
|
+
private_constant :Success, :Failure
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def call(&operation)
|
|
11
|
+
def self.call(&operation)
|
|
13
12
|
results = ::Queue.new
|
|
14
13
|
worker = Thread.new { execute(results, operation) }
|
|
15
14
|
worker.report_on_exception = false
|
|
16
15
|
result = results.pop
|
|
17
16
|
worker.join
|
|
18
|
-
raise result.error if result.
|
|
17
|
+
raise result.error if result.is_a?(Failure)
|
|
19
18
|
|
|
20
19
|
result.value
|
|
21
20
|
end
|
|
22
21
|
|
|
23
|
-
def execute(results, operation)
|
|
24
|
-
results <<
|
|
22
|
+
def self.execute(results, operation)
|
|
23
|
+
results << Success.new(value: operation.call)
|
|
25
24
|
rescue StandardError => e
|
|
26
|
-
results <<
|
|
25
|
+
results << Failure.new(error: e)
|
|
27
26
|
end
|
|
28
27
|
private_class_method :execute
|
|
29
28
|
end
|
|
@@ -21,7 +21,7 @@ module Volcano
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def complete_publication(channel, publication)
|
|
24
|
-
current = @stream_positions
|
|
24
|
+
current = @stream_positions.fetch(channel, nil)
|
|
25
25
|
return unless current
|
|
26
26
|
|
|
27
27
|
completed = publication_position(publication, current)
|
|
@@ -49,7 +49,7 @@ module Volcano
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def mark_publication_gap(channel, publication)
|
|
52
|
-
current = @stream_positions
|
|
52
|
+
current = @stream_positions.fetch(channel, nil)
|
|
53
53
|
return unless current
|
|
54
54
|
|
|
55
55
|
gap = publication_position(publication, current)
|
|
@@ -68,7 +68,7 @@ module Volcano
|
|
|
68
68
|
def store_earliest_gap(channel, gap)
|
|
69
69
|
existing = @position_gaps[channel]
|
|
70
70
|
return if existing == true
|
|
71
|
-
return if existing && existing.fetch(:offset) <= gap.fetch(:offset)
|
|
71
|
+
return if existing.is_a?(Hash) && existing.fetch(:offset) <= gap.fetch(:offset)
|
|
72
72
|
|
|
73
73
|
@position_gaps[channel] = gap
|
|
74
74
|
end
|
|
@@ -84,7 +84,9 @@ module Volcano
|
|
|
84
84
|
return unless epoch.is_a?(String) && !epoch.empty?
|
|
85
85
|
return unless offset.is_a?(Integer) && offset >= 0
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
# @type var position: position
|
|
88
|
+
position = { epoch: epoch.dup.freeze, offset: offset.freeze }
|
|
89
|
+
position.freeze
|
|
88
90
|
end
|
|
89
91
|
|
|
90
92
|
def same_epoch?(first, second) = first.fetch(:epoch) == second.fetch(:epoch)
|
|
@@ -95,7 +97,10 @@ module Volcano
|
|
|
95
97
|
|
|
96
98
|
def completion_before_gap?(channel, completed)
|
|
97
99
|
gap = @position_gaps[channel]
|
|
98
|
-
|
|
100
|
+
return false if gap == true
|
|
101
|
+
return true unless gap.is_a?(Hash)
|
|
102
|
+
|
|
103
|
+
completed.fetch(:offset) < gap.fetch(:offset)
|
|
99
104
|
end
|
|
100
105
|
|
|
101
106
|
def mark_unknown_gap(channel) = @position_gaps[channel] = true
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Volcano
|
|
4
|
-
SignUpResult = Data.define(:confirmation_required, :message, :session)
|
|
4
|
+
SignUpResult = Data.define(:confirmation_required, :message, :session)
|
|
5
|
+
|
|
6
|
+
# Reopen the generated Data class so Steep can check its initializer.
|
|
7
|
+
class SignUpResult
|
|
8
|
+
# @dynamic confirmation_required, message, session, members, with, to_h, deconstruct, deconstruct_keys
|
|
9
|
+
# @dynamic self.[], self.members
|
|
5
10
|
def initialize(confirmation_required:, message:, session: nil)
|
|
6
11
|
super
|
|
7
12
|
end
|
data/lib/volcano/version.rb
CHANGED
data/lib/volcano.rb
CHANGED
|
@@ -50,6 +50,7 @@ require_relative 'volcano/lock_guard'
|
|
|
50
50
|
require_relative 'volcano/lock_renewer'
|
|
51
51
|
require_relative 'volcano/lock_session'
|
|
52
52
|
require_relative 'volcano/lock_auto_renewal'
|
|
53
|
+
require_relative 'volcano/lock_response'
|
|
53
54
|
require_relative 'volcano/locks'
|
|
54
55
|
require_relative 'volcano/realtime/protocol'
|
|
55
56
|
require_relative 'volcano/realtime'
|
|
@@ -57,7 +58,7 @@ require_relative 'volcano/client'
|
|
|
57
58
|
|
|
58
59
|
# Public namespace for the Volcano Ruby SDK.
|
|
59
60
|
module Volcano
|
|
60
|
-
private_constant :GeneratedTransport, :LockAutoRenewal, :LockLeaseClock, :LockRenewer, :LockSession,
|
|
61
|
+
private_constant :GeneratedTransport, :LockAutoRenewal, :LockLeaseClock, :LockRenewer, :LockSession, :LockResponse,
|
|
61
62
|
:Redaction, :SessionOperations
|
|
62
63
|
|
|
63
64
|
Realtime.private_constant :Protocol, :ProtocolDispatch, :ProtocolPublicationDispatch, :ProtocolRecovery,
|
data/sig/lock_guard.rbs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Volcano
|
|
2
|
+
interface _LeaseStartedAt
|
|
3
|
+
def monotonic: () -> Float
|
|
4
|
+
def wall: () -> Time
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class LockGuard
|
|
8
|
+
EXPIRY_MESSAGE: String
|
|
9
|
+
MAX_EXPIRY_POLL_SECONDS: Float
|
|
10
|
+
UNSAFE_RENEWAL_MESSAGE: String
|
|
11
|
+
|
|
12
|
+
attr_reader ttl: Integer
|
|
13
|
+
|
|
14
|
+
def initialize: (LockLease lease, ttl: Integer, started_at: _LeaseStartedAt) -> void
|
|
15
|
+
def lease: () -> LockLease
|
|
16
|
+
def lost?: () -> bool
|
|
17
|
+
# The timeout must be a finite real number.
|
|
18
|
+
def wait_lost: (?timeout: Numeric?) -> bool
|
|
19
|
+
def failure: () -> StandardError?
|
|
20
|
+
end
|
|
21
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: volcano-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.29.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kong
|
|
@@ -560,6 +560,7 @@ files:
|
|
|
560
560
|
- lib/volcano/lock_guard.rb
|
|
561
561
|
- lib/volcano/lock_lease_clock.rb
|
|
562
562
|
- lib/volcano/lock_renewer.rb
|
|
563
|
+
- lib/volcano/lock_response.rb
|
|
563
564
|
- lib/volcano/lock_session.rb
|
|
564
565
|
- lib/volcano/locks.rb
|
|
565
566
|
- lib/volcano/log_responses.rb
|
|
@@ -609,6 +610,7 @@ files:
|
|
|
609
610
|
- sig/email_change_result.rbs
|
|
610
611
|
- sig/errors.rbs
|
|
611
612
|
- sig/function_response.rbs
|
|
613
|
+
- sig/lock_guard.rbs
|
|
612
614
|
- sig/lock_records.rbs
|
|
613
615
|
- sig/log_responses.rbs
|
|
614
616
|
- sig/oauth_records.rbs
|