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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d244570ed2e33751efeb30aa873400168dd80c0c490cf4536ce5dbb6a33f057b
4
- data.tar.gz: ef977dcbbff49ebcb7e43ab1cfdf9aa292a58816281a48988af2de203c8c4dca
3
+ metadata.gz: e946d4476603cf2c234194f51e63aadd8ca1327719bcae02bf098de61049b65b
4
+ data.tar.gz: 38d3aa7dbbc508796620f75285b2a483b70a9e2d49a255aded0dba3fa023334b
5
5
  SHA512:
6
- metadata.gz: c8f7c362b7f9c3c7c00dc91409e8816c941e2c2244b2b2e1f2035c3c4c40f2aef9a91eec84701cb4230c4ad741ec3a4fe80063a42592012ce8024532b753f698
7
- data.tar.gz: f1c26e610f4739303885d5a1d4aa03f86117bc74e4228329e21ef91e379e9f39c55bbee46569dc73ceecb4a68e03d13853e15dcf4cec712ea44fe7d7e6d47bff
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) do
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
- return nil unless nonempty_url?(value)
50
+ url = nonempty_url(value)
51
+ return nil unless url
55
52
 
56
- uri = URI.parse(value)
53
+ uri = URI.parse(url)
57
54
  return nil unless usable_address?(uri)
58
55
 
59
- usable_scheme?(uri.scheme, api_url) ? value : nil
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[key]
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?(value)
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
- next if @entries.size <= MAX_ENTRIES
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
- @entries.delete(@entries.min_by { |_, entry| entry.expires_at }.first) while @entries.size > MAX_ENTRIES
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) do
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
- super(
8
- data: immutable_json(data),
9
- status: status,
10
- headers: immutable_json(headers),
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
@@ -98,7 +98,7 @@ module Volcano
98
98
  end
99
99
 
100
100
  def cached_resolution(cached)
101
- cached.resolution || raise(cached.failure.exception)
101
+ cached.resolution || raise(FunctionResolution.error_for(cached.failure))
102
102
  end
103
103
 
104
104
  def validate_invocation(name, payload)
@@ -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(key, token, request_id, body)
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)
@@ -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
- timeout && (@lease_clock.monotonic_now + timeout)
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
@@ -22,10 +22,11 @@ module Volcano
22
22
 
23
23
  def stop
24
24
  request_stop
25
- return unless @thread
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
- @thread.join(@config.shutdown_timeout)
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
@@ -44,6 +44,7 @@ module Volcano
44
44
  end
45
45
 
46
46
  def cleanup(completed)
47
+ # @type var failure: StandardError?
47
48
  failure = nil
48
49
  @guard.stop_expiry_watch
49
50
  failure = @guard.failure
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 = lock_request(:get_project_lock, 200, key: key, request_id: request_id)
18
- LockState.new(
19
- held: payload.fetch('held'),
20
- expires_at: parse_time(payload['expires_at']),
21
- fencing_token: payload['fencing_token']
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
- parameters = {
28
- authorization: @client.service_token.dup.freeze, key: key.dup.freeze,
29
- ttl: ttl, token: request_uuid(token, 'token'), request_id: request_uuid(request_id, 'request_id')
30
- }.freeze
31
- payload = acquire_payload(parameters)
32
- build_lease(parameters[:key], parameters[:token], payload)
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 = lock_request(:renew_project_lock, 200, key: key, ttl: ttl,
38
- token: lease.token, request_id: request_id)
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
- lock_request(:release_project_lock, 204, key: key, token: lease.token, request_id: request_id)
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
- lock_request(:force_release_project_lock, 204, key: key, request_id: request_id)
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(parameters)
55
- perform_request(:acquire_project_lock, 201, parameters)
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(:acquire_project_lock, 201, parameters)
60
- end
61
-
62
- def lock_request(operation, status, **parameters)
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(operation, status, parameters)
69
- response = Transport.invoke { @transport.public_send(operation, **parameters) }
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
- valid = value.is_a?(String) && value.match?(/\A[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}\z/i)
77
- raise ArgumentError, "#{name} must be a UUID string" unless valid
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: parse_time(payload['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 parse_time(value)
90
- value.is_a?(String) ? Time.iso8601(value) : value
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 = Data.define(:data, :limit, :has_more, :next_cursor) do
26
+ class LogSearchResponse
25
27
  include ImmutableLogJSON
26
28
 
27
29
  def initialize(data:, limit:, has_more:, next_cursor: nil)
28
- super(
29
- data: immutable_json(data), limit: limit, has_more: has_more,
30
- next_cursor: next_cursor&.dup&.freeze
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 = Data.define(:data, :total) do
39
+ class LogActivityResponse
37
40
  include ImmutableLogJSON
38
41
 
39
42
  def initialize(data:, total:)
40
- super(data: immutable_json(data), total: total)
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
- Result = Data.define(:value, :error)
8
- private_constant :Result
7
+ Success = Data.define(:value)
8
+ Failure = Data.define(:error)
9
+ private_constant :Success, :Failure
9
10
 
10
- module_function
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.error
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 << Result.new(value: operation.call, error: nil)
22
+ def self.execute(results, operation)
23
+ results << Success.new(value: operation.call)
25
24
  rescue StandardError => e
26
- results << Result.new(value: nil, error: e)
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[channel]
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[channel]
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
- { epoch: epoch.dup.freeze, offset: offset.freeze }.freeze
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
- gap != true && (!gap || completed.fetch(:offset) < gap.fetch(:offset))
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) do
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Volcano
4
- VERSION = '0.27.0'
4
+ VERSION = '0.29.0'
5
5
  end
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,
@@ -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.27.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