statelydb 0.14.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/api/db/put_pb.rb +1 -1
- data/lib/common/auth/auth_token_provider.rb +27 -38
- data/lib/common/auth/token_fetcher.rb +45 -41
- data/lib/error.rb +5 -2
- data/lib/statelydb.rb +11 -2
- data/lib/transaction/transaction.rb +11 -2
- data/sig/statelydb.rbi +42 -70
- data/sig/statelydb.rbs +30 -56
- 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: acc7d4cbc70b66408fc0723cb627b291114ea531eabf57491d668bd4be9c6dc6
|
4
|
+
data.tar.gz: 4758fd8040faca40481b98aa713c12f711c353cbdfc2141e604227276da59e9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9338ba66b860a68ba965534743dc9f119c19d7db3196432f003db98d056a2ac33f4ce600064200b44e61d355750bc1c2ff1ac1fe378ac0618c5716aea19de8f0
|
7
|
+
data.tar.gz: 44c1c821cde2adc873cb223b3459744959dbe4ab625ddf9da76a9f47e7662cdcd028a6a471f0243fdefea30c419e1e8c8c28c251c776b66b8c8168675dbc27c9
|
data/lib/api/db/put_pb.rb
CHANGED
@@ -7,7 +7,7 @@ require 'google/protobuf'
|
|
7
7
|
require 'api/db/item_pb'
|
8
8
|
|
9
9
|
|
10
|
-
descriptor_data = "\n\x0c\x64\x62/put.proto\x12\nstately.db\x1a\rdb/item.proto\"|\n\nPutRequest\x12\x19\n\x08store_id\x18\x01 \x01(\x04R\x07storeId\x12\'\n\x04puts\x18\x02 \x03(\x0b\x32\x13.stately.db.PutItemR\x04puts\x12*\n\x11schema_version_id\x18\x03 \x01(\rR\x0fschemaVersionId\"
|
10
|
+
descriptor_data = "\n\x0c\x64\x62/put.proto\x12\nstately.db\x1a\rdb/item.proto\"|\n\nPutRequest\x12\x19\n\x08store_id\x18\x01 \x01(\x04R\x07storeId\x12\'\n\x04puts\x18\x02 \x03(\x0b\x32\x13.stately.db.PutItemR\x04puts\x12*\n\x11schema_version_id\x18\x03 \x01(\rR\x0fschemaVersionId\"\x99\x01\n\x07PutItem\x12$\n\x04item\x18\x01 \x01(\x0b\x32\x10.stately.db.ItemR\x04item\x12\x42\n\x1doverwrite_metadata_timestamps\x18\x02 \x01(\x08R\x1boverwriteMetadataTimestamps\x12$\n\x0emust_not_exist\x18\x03 \x01(\x08R\x0cmustNotExist\"5\n\x0bPutResponse\x12&\n\x05items\x18\x01 \x03(\x0b\x32\x10.stately.db.ItemR\x05itemsBc\n\x0e\x63om.stately.dbB\x08PutProtoP\x01\xa2\x02\x03SDX\xaa\x02\nStately.Db\xca\x02\nStately\\Db\xe2\x02\x16Stately\\Db\\GPBMetadata\xea\x02\x0bStately::Dbb\x06proto3"
|
11
11
|
|
12
12
|
pool = Google::Protobuf::DescriptorPool.generated_pool
|
13
13
|
pool.add_serialized_file(descriptor_data)
|
@@ -13,33 +13,28 @@ require_relative "../../error"
|
|
13
13
|
|
14
14
|
LOGGER = Logger.new($stdout)
|
15
15
|
LOGGER.level = Logger::WARN
|
16
|
-
DEFAULT_GRANT_TYPE = "client_credentials"
|
17
16
|
|
18
17
|
# A module for Stately Cloud auth code
|
19
18
|
module StatelyDB
|
20
19
|
module Common
|
21
20
|
# A module for Stately Cloud auth code
|
22
21
|
module Auth
|
23
|
-
#
|
24
|
-
# which vends tokens from
|
25
|
-
# It will default to using the
|
26
|
-
# no credentials are explicitly passed and will throw an error if
|
22
|
+
# AuthTokenProvider is an implementation of the TokenProvider abstract base class
|
23
|
+
# which vends tokens from the StatelyDB auth API.
|
24
|
+
# It will default to using the value of `STATELY_ACCESS_KEY` if
|
25
|
+
# no credentials are explicitly passed and will throw an error if no credentials are found.
|
27
26
|
class AuthTokenProvider < TokenProvider
|
28
|
-
# @param [String] origin The origin of the
|
29
|
-
# @param [String] audience The OAuth Audience for the token
|
30
|
-
# @param [String] client_secret The StatelyDB client secret credential
|
31
|
-
# @param [String] client_id The StatelyDB client ID credential
|
27
|
+
# @param [String] origin The origin of the auth server
|
32
28
|
# @param [String] access_key The StatelyDB access key credential
|
29
|
+
# @param [Float] base_retry_backoff_secs The base retry backoff in seconds
|
33
30
|
def initialize(
|
34
|
-
origin: "https://
|
35
|
-
|
36
|
-
|
37
|
-
client_id: ENV.fetch("STATELY_CLIENT_ID", nil),
|
38
|
-
access_key: ENV.fetch("STATELY_ACCESS_KEY", nil)
|
31
|
+
origin: "https://api.stately.cloud",
|
32
|
+
access_key: ENV.fetch("STATELY_ACCESS_KEY", nil),
|
33
|
+
base_retry_backoff_secs: 1
|
39
34
|
)
|
40
35
|
super()
|
41
|
-
@actor = Async::Actor.new(Actor.new(origin: origin,
|
42
|
-
|
36
|
+
@actor = Async::Actor.new(Actor.new(origin: origin, access_key: access_key,
|
37
|
+
base_retry_backoff_secs: base_retry_backoff_secs))
|
43
38
|
# this initialization cannot happen in the constructor because it is async and must run on the event loop
|
44
39
|
# which is not available in the constructor
|
45
40
|
@actor.init
|
@@ -61,32 +56,26 @@ module StatelyDB
|
|
61
56
|
# This is designed to be used with Async::Actor and run on a dedicated thread.
|
62
57
|
class Actor
|
63
58
|
# @param [String] origin The origin of the OAuth server
|
64
|
-
# @param [String]
|
65
|
-
# @param [
|
66
|
-
|
67
|
-
def initialize(
|
68
|
-
origin:,
|
69
|
-
audience:,
|
70
|
-
client_secret:,
|
71
|
-
client_id:,
|
72
|
-
access_key:
|
73
|
-
)
|
59
|
+
# @param [String] access_key The StatelyDB access key credential
|
60
|
+
# @param [Float] base_retry_backoff_secs The base retry backoff in seconds
|
61
|
+
def initialize(origin:, access_key:, base_retry_backoff_secs:)
|
74
62
|
super()
|
75
63
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
"STATELY_CLIENT_SECRET environment variables. Either pass your credentials in " \
|
85
|
-
"explicitly or set these environment variables",
|
86
|
-
code: GRPC::Core::StatusCodes::UNAUTHENTICATED,
|
87
|
-
stately_code: "Unauthenticated")
|
64
|
+
if access_key.nil?
|
65
|
+
raise StatelyDB::Error.new(
|
66
|
+
"Unable to find an access key in the STATELY_ACCESS_KEY " \
|
67
|
+
"environment variable. Either pass your credentials in " \
|
68
|
+
"the options when creating a client or set this environment variable.",
|
69
|
+
code: GRPC::Core::StatusCodes::UNAUTHENTICATED,
|
70
|
+
stately_code: "Unauthenticated"
|
71
|
+
)
|
88
72
|
end
|
89
73
|
|
74
|
+
@token_fetcher = StatelyDB::Common::Auth::StatelyAccessTokenFetcher.new(
|
75
|
+
origin: origin,
|
76
|
+
access_key: access_key,
|
77
|
+
base_retry_backoff_secs: base_retry_backoff_secs
|
78
|
+
)
|
90
79
|
@token_state = nil
|
91
80
|
@pending_refresh = nil
|
92
81
|
end
|
@@ -37,51 +37,24 @@ module StatelyDB
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
# Auth0TokenFetcher is a TokenFetcher that fetches tokens from an Auth0 server
|
41
|
-
class Auth0TokenFetcher < TokenFetcher
|
42
|
-
# @param [String] origin The origin of the OAuth server
|
43
|
-
# @param [String] audience The OAuth Audience for the token
|
44
|
-
# @param [String] client_secret The StatelyDB client secret credential
|
45
|
-
# @param [String] client_id The StatelyDB client ID credential
|
46
|
-
def initialize(origin:, audience:, client_secret:, client_id:)
|
47
|
-
super()
|
48
|
-
@client = Async::HTTP::Client.new(Async::HTTP::Endpoint.parse(origin))
|
49
|
-
@audience = audience
|
50
|
-
@client_secret = client_secret
|
51
|
-
@client_id = client_id
|
52
|
-
end
|
53
|
-
|
54
|
-
# Fetch a new token from auth0
|
55
|
-
# @return [TokenResult] The fetched TokenResult
|
56
|
-
def fetch
|
57
|
-
headers = [["content-type", "application/json"]]
|
58
|
-
body = JSON.dump({ "client_id" => @client_id, client_secret: @client_secret, audience: @audience,
|
59
|
-
grant_type: DEFAULT_GRANT_TYPE })
|
60
|
-
Sync do
|
61
|
-
# TODO: Wrap this in a retry loop and parse errors like we
|
62
|
-
# do in the Go SDK.
|
63
|
-
response = @client.post("/oauth/token", headers, body)
|
64
|
-
raise "Auth request failed" if response.status != 200
|
65
|
-
|
66
|
-
resp_data = JSON.parse(response.read)
|
67
|
-
TokenResult.new(token: resp_data["access_token"], expires_in_secs: resp_data["expires_in"])
|
68
|
-
ensure
|
69
|
-
response&.close
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def close
|
74
|
-
@client&.close
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
40
|
# StatelyAccessTokenFetcher is a TokenFetcher that fetches tokens from the StatelyDB API
|
79
41
|
class StatelyAccessTokenFetcher < TokenFetcher
|
42
|
+
NON_RETRYABLE_ERRORS = [
|
43
|
+
GRPC::Core::StatusCodes::UNAUTHENTICATED,
|
44
|
+
GRPC::Core::StatusCodes::PERMISSION_DENIED,
|
45
|
+
GRPC::Core::StatusCodes::NOT_FOUND,
|
46
|
+
GRPC::Core::StatusCodes::UNIMPLEMENTED,
|
47
|
+
GRPC::Core::StatusCodes::INVALID_ARGUMENT
|
48
|
+
].freeze
|
49
|
+
RETRY_ATTEMPTS = 10
|
50
|
+
|
80
51
|
# @param [String] origin The origin of the OAuth server
|
81
52
|
# @param [String] access_key The StatelyDB access key credential
|
82
|
-
|
53
|
+
# @param [Float] base_retry_backoff_secs The base backoff time in seconds
|
54
|
+
def initialize(origin:, access_key:, base_retry_backoff_secs:)
|
83
55
|
super()
|
84
56
|
@access_key = access_key
|
57
|
+
@base_retry_backoff_secs = base_retry_backoff_secs
|
85
58
|
@channel = Common::Net.new_channel(endpoint: origin)
|
86
59
|
error_interceptor = Common::ErrorInterceptor.new
|
87
60
|
@stub = Stately::Auth::AuthService::Stub.new(nil, nil, channel_override: @channel,
|
@@ -91,14 +64,45 @@ module StatelyDB
|
|
91
64
|
# Fetch a new token from the StatelyDB API
|
92
65
|
# @return [TokenResult] The fetched TokenResult
|
93
66
|
def fetch
|
94
|
-
|
95
|
-
|
67
|
+
RETRY_ATTEMPTS.times do |i|
|
68
|
+
resp = @stub.get_auth_token(Stately::Auth::GetAuthTokenRequest.new(access_key: @access_key))
|
69
|
+
return TokenResult.new(token: resp.auth_token, expires_in_secs: resp.expires_in_s)
|
70
|
+
rescue StatelyDB::Error => e
|
71
|
+
# raise if it's the final attempt or if the error is not retryable
|
72
|
+
raise e unless self.class.retryable_error?(e) && i < RETRY_ATTEMPTS - 1
|
73
|
+
|
74
|
+
# exponential backoff
|
75
|
+
sleep(backoff(i, @base_retry_backoff_secs))
|
76
|
+
end
|
96
77
|
end
|
97
78
|
|
98
79
|
def close
|
99
80
|
@channel&.close
|
100
81
|
end
|
82
|
+
|
83
|
+
# Check if an error is retryable
|
84
|
+
# @param [StatelyDB::Error] err The error to check
|
85
|
+
# @return [Boolean] True if the error is retryable
|
86
|
+
def self.retryable_error?(err)
|
87
|
+
!NON_RETRYABLE_ERRORS.include?(err.code)
|
88
|
+
end
|
101
89
|
end
|
102
90
|
end
|
103
91
|
end
|
104
92
|
end
|
93
|
+
|
94
|
+
# backoff returns a duration to wait before retrying a request. `attempt` is
|
95
|
+
# the current attempt number, starting from 0 (e.g. the first attempt is 0,
|
96
|
+
# then 1, then 2...).
|
97
|
+
#
|
98
|
+
# @param [Integer] attempt The current attempt number
|
99
|
+
# @param [Float] base_backoff The base backoff time in seconds
|
100
|
+
# @return [Float] The duration in seconds to wait before retrying
|
101
|
+
def backoff(attempt, base_backoff)
|
102
|
+
# Double the base backoff time per attempt, starting with 1
|
103
|
+
exp = 2**attempt
|
104
|
+
# Add a full jitter to the backoff time, from no wait to 100% of the exponential backoff.
|
105
|
+
# See https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
|
106
|
+
jitter = rand
|
107
|
+
(exp * jitter * base_backoff)
|
108
|
+
end
|
data/lib/error.rb
CHANGED
@@ -41,9 +41,12 @@ module StatelyDB
|
|
41
41
|
raw_detail = status.details[0]
|
42
42
|
if raw_detail.type_url == "type.googleapis.com/stately.errors.StatelyErrorDetails"
|
43
43
|
error_details = Stately::Errors::StatelyErrorDetails.decode(raw_detail.value)
|
44
|
+
message = error_details.message
|
45
|
+
rid = error.metadata["st-rid"]
|
46
|
+
message = "#{message} (Request ID: #{rid})" unless rid.nil?
|
44
47
|
upstream_cause = error_details.upstream_cause.empty? ? nil : StandardError.new(error_details.upstream_cause) # rubocop:disable Metrics/BlockNesting
|
45
|
-
return new(
|
46
|
-
|
48
|
+
return new(message, code: error.code, stately_code: error_details.stately_code,
|
49
|
+
cause: upstream_cause)
|
47
50
|
end
|
48
51
|
end
|
49
52
|
end
|
data/lib/statelydb.rb
CHANGED
@@ -188,12 +188,20 @@ module StatelyDB
|
|
188
188
|
# `initialValue` field in its key, that initial value will automatically
|
189
189
|
# be chosen not to conflict with existing items, so this condition only
|
190
190
|
# applies to key paths that do not contain the `initialValue` field.
|
191
|
+
# @param overwrite_metadata_timestamps [Boolean] If set to true, the server will
|
192
|
+
# set the `createdAtTime` and/or `lastModifiedAtTime` fields based on the
|
193
|
+
# current values in this item (assuming you've mapped them to a field using
|
194
|
+
# `fromMetadata`). Without this, those fields are always ignored and the
|
195
|
+
# server sets them to the appropriate times. This option can be useful when
|
196
|
+
# migrating data from another system.
|
191
197
|
# @return [StatelyDB::Item] the item that was stored
|
192
198
|
#
|
193
199
|
# @example client.data.put(my_item)
|
194
200
|
# @example client.data.put(my_item, must_not_exist: true)
|
195
|
-
def put(item,
|
196
|
-
|
201
|
+
def put(item,
|
202
|
+
must_not_exist: false,
|
203
|
+
overwrite_metadata_timestamps: false)
|
204
|
+
resp = put_batch({ item:, must_not_exist:, overwrite_metadata_timestamps: })
|
197
205
|
|
198
206
|
# Always return a single Item.
|
199
207
|
resp.first
|
@@ -215,6 +223,7 @@ module StatelyDB
|
|
215
223
|
item = input[:item]
|
216
224
|
Stately::Db::PutItem.new(
|
217
225
|
item: item.send("marshal_stately"),
|
226
|
+
overwrite_metadata_timestamps: input[:overwrite_metadata_timestamps],
|
218
227
|
must_not_exist: input[:must_not_exist]
|
219
228
|
)
|
220
229
|
else
|
@@ -233,6 +233,12 @@ module StatelyDB
|
|
233
233
|
# `initialValue` field in its key, that initial value will automatically
|
234
234
|
# be chosen not to conflict with existing items, so this condition only
|
235
235
|
# applies to key paths that do not contain the `initialValue` field.
|
236
|
+
# @param overwrite_metadata_timestamps [Boolean] If set to true, the server will
|
237
|
+
# set the `createdAtTime` and/or `lastModifiedAtTime` fields based on the
|
238
|
+
# current values in this item (assuming you've mapped them to a field using
|
239
|
+
# `fromMetadata`). Without this, those fields are always ignored and the
|
240
|
+
# server sets them to the appropriate times. This option can be useful when
|
241
|
+
# migrating data from another system.
|
236
242
|
# @return [String, Integer] the id of the item
|
237
243
|
#
|
238
244
|
# @example
|
@@ -242,8 +248,10 @@ module StatelyDB
|
|
242
248
|
# results.puts.each do |result|
|
243
249
|
# puts result.key_path
|
244
250
|
# end
|
245
|
-
def put(item,
|
246
|
-
|
251
|
+
def put(item,
|
252
|
+
must_not_exist: false,
|
253
|
+
overwrite_metadata_timestamps: false)
|
254
|
+
resp = put_batch({ item:, must_not_exist:, overwrite_metadata_timestamps: })
|
247
255
|
resp.first
|
248
256
|
end
|
249
257
|
|
@@ -269,6 +277,7 @@ module StatelyDB
|
|
269
277
|
item = input[:item]
|
270
278
|
Stately::Db::PutItem.new(
|
271
279
|
item: item.send("marshal_stately"),
|
280
|
+
overwrite_metadata_timestamps: input[:overwrite_metadata_timestamps],
|
272
281
|
must_not_exist: input[:must_not_exist]
|
273
282
|
)
|
274
283
|
else
|
data/sig/statelydb.rbi
CHANGED
@@ -313,6 +313,8 @@ module StatelyDB
|
|
313
313
|
#
|
314
314
|
# _@param_ `must_not_exist` — A condition that indicates this item must not already exist at any of its key paths. If there is already an item at one of those paths, the Put operation will fail with a "ConditionalCheckFailed" error. Note that if the item has an `initialValue` field in its key, that initial value will automatically be chosen not to conflict with existing items, so this condition only applies to key paths that do not contain the `initialValue` field.
|
315
315
|
#
|
316
|
+
# _@param_ `overwrite_metadata_timestamps` — If set to true, the server will set the `createdAtTime` and/or `lastModifiedAtTime` fields based on the current values in this item (assuming you've mapped them to a field using `fromMetadata`). Without this, those fields are always ignored and the server sets them to the appropriate times. This option can be useful when migrating data from another system.
|
317
|
+
#
|
316
318
|
# _@return_ — the item that was stored
|
317
319
|
#
|
318
320
|
# client.data.put(my_item)
|
@@ -322,8 +324,8 @@ module StatelyDB
|
|
322
324
|
# client.data.put(my_item, must_not_exist: true)
|
323
325
|
# ```ruby
|
324
326
|
# ```
|
325
|
-
sig { params(item: StatelyDB::Item, must_not_exist: T::Boolean).returns(StatelyDB::Item) }
|
326
|
-
def put(item, must_not_exist: false); end
|
327
|
+
sig { params(item: StatelyDB::Item, must_not_exist: T::Boolean, overwrite_metadata_timestamps: T::Boolean).returns(StatelyDB::Item) }
|
328
|
+
def put(item, must_not_exist: false, overwrite_metadata_timestamps: false); end
|
327
329
|
|
328
330
|
# Put a batch of up to 50 Items into a StatelyDB Store.
|
329
331
|
#
|
@@ -605,42 +607,24 @@ module StatelyDB
|
|
605
607
|
def close; end
|
606
608
|
end
|
607
609
|
|
608
|
-
# Auth0TokenFetcher is a TokenFetcher that fetches tokens from an Auth0 server
|
609
|
-
class Auth0TokenFetcher < StatelyDB::Common::Auth::TokenFetcher
|
610
|
-
# _@param_ `origin` — The origin of the OAuth server
|
611
|
-
#
|
612
|
-
# _@param_ `audience` — The OAuth Audience for the token
|
613
|
-
#
|
614
|
-
# _@param_ `client_secret` — The StatelyDB client secret credential
|
615
|
-
#
|
616
|
-
# _@param_ `client_id` — The StatelyDB client ID credential
|
617
|
-
sig do
|
618
|
-
params(
|
619
|
-
origin: String,
|
620
|
-
audience: String,
|
621
|
-
client_secret: String,
|
622
|
-
client_id: String
|
623
|
-
).void
|
624
|
-
end
|
625
|
-
def initialize(origin:, audience:, client_secret:, client_id:); end
|
626
|
-
|
627
|
-
# Fetch a new token from auth0
|
628
|
-
#
|
629
|
-
# _@return_ — The fetched TokenResult
|
630
|
-
sig { returns(TokenResult) }
|
631
|
-
def fetch; end
|
632
|
-
|
633
|
-
sig { returns(T.untyped) }
|
634
|
-
def close; end
|
635
|
-
end
|
636
|
-
|
637
610
|
# StatelyAccessTokenFetcher is a TokenFetcher that fetches tokens from the StatelyDB API
|
638
611
|
class StatelyAccessTokenFetcher < StatelyDB::Common::Auth::TokenFetcher
|
612
|
+
NON_RETRYABLE_ERRORS = T.let([
|
613
|
+
GRPC::Core::StatusCodes::UNAUTHENTICATED,
|
614
|
+
GRPC::Core::StatusCodes::PERMISSION_DENIED,
|
615
|
+
GRPC::Core::StatusCodes::NOT_FOUND,
|
616
|
+
GRPC::Core::StatusCodes::UNIMPLEMENTED,
|
617
|
+
GRPC::Core::StatusCodes::INVALID_ARGUMENT
|
618
|
+
].freeze, T.untyped)
|
619
|
+
RETRY_ATTEMPTS = T.let(10, T.untyped)
|
620
|
+
|
639
621
|
# _@param_ `origin` — The origin of the OAuth server
|
640
622
|
#
|
641
623
|
# _@param_ `access_key` — The StatelyDB access key credential
|
642
|
-
|
643
|
-
|
624
|
+
#
|
625
|
+
# _@param_ `base_retry_backoff_secs` — The base backoff time in seconds
|
626
|
+
sig { params(origin: String, access_key: String, base_retry_backoff_secs: Float).void }
|
627
|
+
def initialize(origin:, access_key:, base_retry_backoff_secs:); end
|
644
628
|
|
645
629
|
# Fetch a new token from the StatelyDB API
|
646
630
|
#
|
@@ -650,6 +634,14 @@ module StatelyDB
|
|
650
634
|
|
651
635
|
sig { returns(T.untyped) }
|
652
636
|
def close; end
|
637
|
+
|
638
|
+
# Check if an error is retryable
|
639
|
+
#
|
640
|
+
# _@param_ `err` — The error to check
|
641
|
+
#
|
642
|
+
# _@return_ — True if the error is retryable
|
643
|
+
sig { params(err: StatelyDB::Error).returns(T::Boolean) }
|
644
|
+
def self.retryable_error?(err); end
|
653
645
|
end
|
654
646
|
|
655
647
|
# TokenProvider is an abstract base class that should be extended
|
@@ -668,30 +660,18 @@ module StatelyDB
|
|
668
660
|
def close; end
|
669
661
|
end
|
670
662
|
|
671
|
-
#
|
672
|
-
# which vends tokens from
|
673
|
-
# It will default to using the
|
674
|
-
# no credentials are explicitly passed and will throw an error if
|
663
|
+
# AuthTokenProvider is an implementation of the TokenProvider abstract base class
|
664
|
+
# which vends tokens from the StatelyDB auth API.
|
665
|
+
# It will default to using the value of `STATELY_ACCESS_KEY` if
|
666
|
+
# no credentials are explicitly passed and will throw an error if no credentials are found.
|
675
667
|
class AuthTokenProvider < StatelyDB::Common::Auth::TokenProvider
|
676
|
-
# _@param_ `origin` — The origin of the
|
677
|
-
#
|
678
|
-
# _@param_ `audience` — The OAuth Audience for the token
|
679
|
-
#
|
680
|
-
# _@param_ `client_secret` — The StatelyDB client secret credential
|
681
|
-
#
|
682
|
-
# _@param_ `client_id` — The StatelyDB client ID credential
|
668
|
+
# _@param_ `origin` — The origin of the auth server
|
683
669
|
#
|
684
670
|
# _@param_ `access_key` — The StatelyDB access key credential
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
client_secret: String,
|
690
|
-
client_id: String,
|
691
|
-
access_key: String
|
692
|
-
).void
|
693
|
-
end
|
694
|
-
def initialize(origin: "https://oauth.stately.cloud", audience: "api.stately.cloud", client_secret: ENV.fetch("STATELY_CLIENT_SECRET", nil), client_id: ENV.fetch("STATELY_CLIENT_ID", nil), access_key: ENV.fetch("STATELY_ACCESS_KEY", nil)); end
|
671
|
+
#
|
672
|
+
# _@param_ `base_retry_backoff_secs` — The base retry backoff in seconds
|
673
|
+
sig { params(origin: String, access_key: String, base_retry_backoff_secs: Float).void }
|
674
|
+
def initialize(origin: "https://api.stately.cloud", access_key: ENV.fetch("STATELY_ACCESS_KEY", nil), base_retry_backoff_secs: 1); end
|
695
675
|
|
696
676
|
# Close the token provider and kill any background operations
|
697
677
|
# This just invokes the close method on the actor which should do the cleanup
|
@@ -709,21 +689,11 @@ module StatelyDB
|
|
709
689
|
class Actor
|
710
690
|
# _@param_ `origin` — The origin of the OAuth server
|
711
691
|
#
|
712
|
-
# _@param_ `
|
692
|
+
# _@param_ `access_key` — The StatelyDB access key credential
|
713
693
|
#
|
714
|
-
# _@param_ `
|
715
|
-
|
716
|
-
|
717
|
-
sig do
|
718
|
-
params(
|
719
|
-
origin: String,
|
720
|
-
audience: String,
|
721
|
-
client_secret: String,
|
722
|
-
client_id: String,
|
723
|
-
access_key: T.untyped
|
724
|
-
).void
|
725
|
-
end
|
726
|
-
def initialize(origin:, audience:, client_secret:, client_id:, access_key:); end
|
694
|
+
# _@param_ `base_retry_backoff_secs` — The base retry backoff in seconds
|
695
|
+
sig { params(origin: String, access_key: String, base_retry_backoff_secs: Float).void }
|
696
|
+
def initialize(origin:, access_key:, base_retry_backoff_secs:); end
|
727
697
|
|
728
698
|
# Initialize the actor. This runs on the actor thread which means
|
729
699
|
# we can dispatch async operations here.
|
@@ -973,6 +943,8 @@ module StatelyDB
|
|
973
943
|
#
|
974
944
|
# _@param_ `must_not_exist` — A condition that indicates this item must not already exist at any of its key paths. If there is already an item at one of those paths, the Put operation will fail with a "ConditionalCheckFailed" error. Note that if the item has an `initialValue` field in its key, that initial value will automatically be chosen not to conflict with existing items, so this condition only applies to key paths that do not contain the `initialValue` field.
|
975
945
|
#
|
946
|
+
# _@param_ `overwrite_metadata_timestamps` — If set to true, the server will set the `createdAtTime` and/or `lastModifiedAtTime` fields based on the current values in this item (assuming you've mapped them to a field using `fromMetadata`). Without this, those fields are always ignored and the server sets them to the appropriate times. This option can be useful when migrating data from another system.
|
947
|
+
#
|
976
948
|
# _@return_ — the id of the item
|
977
949
|
#
|
978
950
|
# ```ruby
|
@@ -980,8 +952,8 @@ module StatelyDB
|
|
980
952
|
# txn.put(my_item)
|
981
953
|
# end
|
982
954
|
# ```
|
983
|
-
sig { params(item: StatelyDB::Item, must_not_exist: T::Boolean).returns(T.any(String, Integer)) }
|
984
|
-
def put(item, must_not_exist: false); end
|
955
|
+
sig { params(item: StatelyDB::Item, must_not_exist: T::Boolean, overwrite_metadata_timestamps: T::Boolean).returns(T.any(String, Integer)) }
|
956
|
+
def put(item, must_not_exist: false, overwrite_metadata_timestamps: false); end
|
985
957
|
|
986
958
|
# Put a batch of up to 50 Items into a StatelyDB Store. Results are not
|
987
959
|
# returned until the transaction is committed and will be available in the
|
data/sig/statelydb.rbs
CHANGED
@@ -267,6 +267,8 @@ module StatelyDB
|
|
267
267
|
#
|
268
268
|
# _@param_ `must_not_exist` — A condition that indicates this item must not already exist at any of its key paths. If there is already an item at one of those paths, the Put operation will fail with a "ConditionalCheckFailed" error. Note that if the item has an `initialValue` field in its key, that initial value will automatically be chosen not to conflict with existing items, so this condition only applies to key paths that do not contain the `initialValue` field.
|
269
269
|
#
|
270
|
+
# _@param_ `overwrite_metadata_timestamps` — If set to true, the server will set the `createdAtTime` and/or `lastModifiedAtTime` fields based on the current values in this item (assuming you've mapped them to a field using `fromMetadata`). Without this, those fields are always ignored and the server sets them to the appropriate times. This option can be useful when migrating data from another system.
|
271
|
+
#
|
270
272
|
# _@return_ — the item that was stored
|
271
273
|
#
|
272
274
|
# client.data.put(my_item)
|
@@ -276,7 +278,7 @@ module StatelyDB
|
|
276
278
|
# client.data.put(my_item, must_not_exist: true)
|
277
279
|
# ```ruby
|
278
280
|
# ```
|
279
|
-
def put: (StatelyDB::Item item, ?must_not_exist: bool) -> StatelyDB::Item
|
281
|
+
def put: (StatelyDB::Item item, ?must_not_exist: bool, ?overwrite_metadata_timestamps: bool) -> StatelyDB::Item
|
280
282
|
|
281
283
|
# Put a batch of up to 50 Items into a StatelyDB Store.
|
282
284
|
#
|
@@ -524,36 +526,17 @@ module StatelyDB
|
|
524
526
|
def close: () -> untyped
|
525
527
|
end
|
526
528
|
|
527
|
-
# Auth0TokenFetcher is a TokenFetcher that fetches tokens from an Auth0 server
|
528
|
-
class Auth0TokenFetcher < StatelyDB::Common::Auth::TokenFetcher
|
529
|
-
# _@param_ `origin` — The origin of the OAuth server
|
530
|
-
#
|
531
|
-
# _@param_ `audience` — The OAuth Audience for the token
|
532
|
-
#
|
533
|
-
# _@param_ `client_secret` — The StatelyDB client secret credential
|
534
|
-
#
|
535
|
-
# _@param_ `client_id` — The StatelyDB client ID credential
|
536
|
-
def initialize: (
|
537
|
-
origin: String,
|
538
|
-
audience: String,
|
539
|
-
client_secret: String,
|
540
|
-
client_id: String
|
541
|
-
) -> void
|
542
|
-
|
543
|
-
# Fetch a new token from auth0
|
544
|
-
#
|
545
|
-
# _@return_ — The fetched TokenResult
|
546
|
-
def fetch: () -> TokenResult
|
547
|
-
|
548
|
-
def close: () -> untyped
|
549
|
-
end
|
550
|
-
|
551
529
|
# StatelyAccessTokenFetcher is a TokenFetcher that fetches tokens from the StatelyDB API
|
552
530
|
class StatelyAccessTokenFetcher < StatelyDB::Common::Auth::TokenFetcher
|
531
|
+
NON_RETRYABLE_ERRORS: untyped
|
532
|
+
RETRY_ATTEMPTS: untyped
|
533
|
+
|
553
534
|
# _@param_ `origin` — The origin of the OAuth server
|
554
535
|
#
|
555
536
|
# _@param_ `access_key` — The StatelyDB access key credential
|
556
|
-
|
537
|
+
#
|
538
|
+
# _@param_ `base_retry_backoff_secs` — The base backoff time in seconds
|
539
|
+
def initialize: (origin: String, access_key: String, base_retry_backoff_secs: Float) -> void
|
557
540
|
|
558
541
|
# Fetch a new token from the StatelyDB API
|
559
542
|
#
|
@@ -561,6 +544,13 @@ module StatelyDB
|
|
561
544
|
def fetch: () -> TokenResult
|
562
545
|
|
563
546
|
def close: () -> untyped
|
547
|
+
|
548
|
+
# Check if an error is retryable
|
549
|
+
#
|
550
|
+
# _@param_ `err` — The error to check
|
551
|
+
#
|
552
|
+
# _@return_ — True if the error is retryable
|
553
|
+
def self.retryable_error?: (StatelyDB::Error err) -> bool
|
564
554
|
end
|
565
555
|
|
566
556
|
# TokenProvider is an abstract base class that should be extended
|
@@ -577,27 +567,17 @@ module StatelyDB
|
|
577
567
|
def close: () -> untyped
|
578
568
|
end
|
579
569
|
|
580
|
-
#
|
581
|
-
# which vends tokens from
|
582
|
-
# It will default to using the
|
583
|
-
# no credentials are explicitly passed and will throw an error if
|
570
|
+
# AuthTokenProvider is an implementation of the TokenProvider abstract base class
|
571
|
+
# which vends tokens from the StatelyDB auth API.
|
572
|
+
# It will default to using the value of `STATELY_ACCESS_KEY` if
|
573
|
+
# no credentials are explicitly passed and will throw an error if no credentials are found.
|
584
574
|
class AuthTokenProvider < StatelyDB::Common::Auth::TokenProvider
|
585
|
-
# _@param_ `origin` — The origin of the
|
586
|
-
#
|
587
|
-
# _@param_ `audience` — The OAuth Audience for the token
|
588
|
-
#
|
589
|
-
# _@param_ `client_secret` — The StatelyDB client secret credential
|
590
|
-
#
|
591
|
-
# _@param_ `client_id` — The StatelyDB client ID credential
|
575
|
+
# _@param_ `origin` — The origin of the auth server
|
592
576
|
#
|
593
577
|
# _@param_ `access_key` — The StatelyDB access key credential
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
?client_secret: String,
|
598
|
-
?client_id: String,
|
599
|
-
?access_key: String
|
600
|
-
) -> void
|
578
|
+
#
|
579
|
+
# _@param_ `base_retry_backoff_secs` — The base retry backoff in seconds
|
580
|
+
def initialize: (?origin: String, ?access_key: String, ?base_retry_backoff_secs: Float) -> void
|
601
581
|
|
602
582
|
# Close the token provider and kill any background operations
|
603
583
|
# This just invokes the close method on the actor which should do the cleanup
|
@@ -613,18 +593,10 @@ module StatelyDB
|
|
613
593
|
class Actor
|
614
594
|
# _@param_ `origin` — The origin of the OAuth server
|
615
595
|
#
|
616
|
-
# _@param_ `
|
617
|
-
#
|
618
|
-
# _@param_ `client_secret` — The StatelyDB client secret credential
|
596
|
+
# _@param_ `access_key` — The StatelyDB access key credential
|
619
597
|
#
|
620
|
-
# _@param_ `
|
621
|
-
def initialize: (
|
622
|
-
origin: String,
|
623
|
-
audience: String,
|
624
|
-
client_secret: String,
|
625
|
-
client_id: String,
|
626
|
-
access_key: untyped
|
627
|
-
) -> void
|
598
|
+
# _@param_ `base_retry_backoff_secs` — The base retry backoff in seconds
|
599
|
+
def initialize: (origin: String, access_key: String, base_retry_backoff_secs: Float) -> void
|
628
600
|
|
629
601
|
# Initialize the actor. This runs on the actor thread which means
|
630
602
|
# we can dispatch async operations here.
|
@@ -838,6 +810,8 @@ module StatelyDB
|
|
838
810
|
#
|
839
811
|
# _@param_ `must_not_exist` — A condition that indicates this item must not already exist at any of its key paths. If there is already an item at one of those paths, the Put operation will fail with a "ConditionalCheckFailed" error. Note that if the item has an `initialValue` field in its key, that initial value will automatically be chosen not to conflict with existing items, so this condition only applies to key paths that do not contain the `initialValue` field.
|
840
812
|
#
|
813
|
+
# _@param_ `overwrite_metadata_timestamps` — If set to true, the server will set the `createdAtTime` and/or `lastModifiedAtTime` fields based on the current values in this item (assuming you've mapped them to a field using `fromMetadata`). Without this, those fields are always ignored and the server sets them to the appropriate times. This option can be useful when migrating data from another system.
|
814
|
+
#
|
841
815
|
# _@return_ — the id of the item
|
842
816
|
#
|
843
817
|
# ```ruby
|
@@ -845,7 +819,7 @@ module StatelyDB
|
|
845
819
|
# txn.put(my_item)
|
846
820
|
# end
|
847
821
|
# ```
|
848
|
-
def put: (StatelyDB::Item item, ?must_not_exist: bool) -> (String | Integer)
|
822
|
+
def put: (StatelyDB::Item item, ?must_not_exist: bool, ?overwrite_metadata_timestamps: bool) -> (String | Integer)
|
849
823
|
|
850
824
|
# Put a batch of up to 50 Items into a StatelyDB Store. Results are not
|
851
825
|
# returned until the transaction is committed and will be available in the
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: statelydb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stately Cloud, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|