statelydb 0.14.0 → 0.15.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/common/auth/auth_token_provider.rb +12 -4
- data/lib/common/auth/token_fetcher.rb +45 -5
- data/sig/statelydb.rbi +33 -6
- data/sig/statelydb.rbs +23 -3
- 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: f1d7563d7f40d84bdc1ef3dacff41707ed1d915b638223d33b488ca4c7de531f
|
4
|
+
data.tar.gz: dd682b92fbc100505e15820c5415acadc9defc6bc2f2d0dad5b5797deddbf24b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0f27aa770fdf0c7b3386ac37862226cb4b5215766d265e47c82323b2157966e6ce0d87b5e4081d8d9dcd549f45cd0f6527203b0025b0e6c62ce0780c81dae74
|
7
|
+
data.tar.gz: de86db0a2a0227e6bec231d11c378bffff42fa7911ccc0874bd3ed97fae7f73d0ac29ce55b31817f75bfa82c0b63daa79dabd28276a66e17e2748770450f6243
|
@@ -30,16 +30,19 @@ module StatelyDB
|
|
30
30
|
# @param [String] client_secret The StatelyDB client secret credential
|
31
31
|
# @param [String] client_id The StatelyDB client ID credential
|
32
32
|
# @param [String] access_key The StatelyDB access key credential
|
33
|
+
# @param [Float] base_retry_backoff_secs The base retry backoff in seconds
|
33
34
|
def initialize(
|
34
35
|
origin: "https://oauth.stately.cloud",
|
35
36
|
audience: "api.stately.cloud",
|
36
37
|
client_secret: ENV.fetch("STATELY_CLIENT_SECRET", nil),
|
37
38
|
client_id: ENV.fetch("STATELY_CLIENT_ID", nil),
|
38
|
-
access_key: ENV.fetch("STATELY_ACCESS_KEY", nil)
|
39
|
+
access_key: ENV.fetch("STATELY_ACCESS_KEY", nil),
|
40
|
+
base_retry_backoff_secs: 1
|
39
41
|
)
|
40
42
|
super()
|
41
43
|
@actor = Async::Actor.new(Actor.new(origin: origin, audience: audience,
|
42
|
-
client_secret: client_secret, client_id: client_id, access_key: access_key
|
44
|
+
client_secret: client_secret, client_id: client_id, access_key: access_key,
|
45
|
+
base_retry_backoff_secs: base_retry_backoff_secs))
|
43
46
|
# this initialization cannot happen in the constructor because it is async and must run on the event loop
|
44
47
|
# which is not available in the constructor
|
45
48
|
@actor.init
|
@@ -64,18 +67,23 @@ module StatelyDB
|
|
64
67
|
# @param [String] audience The OAuth Audience for the token
|
65
68
|
# @param [String] client_secret The StatelyDB client secret credential
|
66
69
|
# @param [String] client_id The StatelyDB client ID credential
|
70
|
+
# @param [String] access_key The StatelyDB access key credential
|
71
|
+
# @param [Float] base_retry_backoff_secs The base retry backoff in seconds
|
67
72
|
def initialize(
|
68
73
|
origin:,
|
69
74
|
audience:,
|
70
75
|
client_secret:,
|
71
76
|
client_id:,
|
72
|
-
access_key
|
77
|
+
access_key:,
|
78
|
+
base_retry_backoff_secs:
|
73
79
|
)
|
74
80
|
super()
|
75
81
|
|
76
82
|
@token_fetcher = nil
|
77
83
|
if !access_key.nil?
|
78
|
-
@token_fetcher = StatelyDB::Common::Auth::StatelyAccessTokenFetcher.new(
|
84
|
+
@token_fetcher = StatelyDB::Common::Auth::StatelyAccessTokenFetcher.new(
|
85
|
+
origin: origin, access_key: access_key, base_retry_backoff_secs: base_retry_backoff_secs
|
86
|
+
)
|
79
87
|
elsif !client_secret.nil? && !client_id.nil?
|
80
88
|
@token_fetcher = StatelyDB::Common::Auth::Auth0TokenFetcher.new(origin: origin, audience: audience,
|
81
89
|
client_secret: client_secret, client_id: client_id)
|
@@ -58,8 +58,6 @@ module StatelyDB
|
|
58
58
|
body = JSON.dump({ "client_id" => @client_id, client_secret: @client_secret, audience: @audience,
|
59
59
|
grant_type: DEFAULT_GRANT_TYPE })
|
60
60
|
Sync do
|
61
|
-
# TODO: Wrap this in a retry loop and parse errors like we
|
62
|
-
# do in the Go SDK.
|
63
61
|
response = @client.post("/oauth/token", headers, body)
|
64
62
|
raise "Auth request failed" if response.status != 200
|
65
63
|
|
@@ -77,11 +75,22 @@ module StatelyDB
|
|
77
75
|
|
78
76
|
# StatelyAccessTokenFetcher is a TokenFetcher that fetches tokens from the StatelyDB API
|
79
77
|
class StatelyAccessTokenFetcher < TokenFetcher
|
78
|
+
NON_RETRYABLE_ERRORS = [
|
79
|
+
GRPC::Core::StatusCodes::UNAUTHENTICATED,
|
80
|
+
GRPC::Core::StatusCodes::PERMISSION_DENIED,
|
81
|
+
GRPC::Core::StatusCodes::NOT_FOUND,
|
82
|
+
GRPC::Core::StatusCodes::UNIMPLEMENTED,
|
83
|
+
GRPC::Core::StatusCodes::INVALID_ARGUMENT
|
84
|
+
].freeze
|
85
|
+
RETRY_ATTEMPTS = 10
|
86
|
+
|
80
87
|
# @param [String] origin The origin of the OAuth server
|
81
88
|
# @param [String] access_key The StatelyDB access key credential
|
82
|
-
|
89
|
+
# @param [Float] base_retry_backoff_secs The base backoff time in seconds
|
90
|
+
def initialize(origin:, access_key:, base_retry_backoff_secs:)
|
83
91
|
super()
|
84
92
|
@access_key = access_key
|
93
|
+
@base_retry_backoff_secs = base_retry_backoff_secs
|
85
94
|
@channel = Common::Net.new_channel(endpoint: origin)
|
86
95
|
error_interceptor = Common::ErrorInterceptor.new
|
87
96
|
@stub = Stately::Auth::AuthService::Stub.new(nil, nil, channel_override: @channel,
|
@@ -91,14 +100,45 @@ module StatelyDB
|
|
91
100
|
# Fetch a new token from the StatelyDB API
|
92
101
|
# @return [TokenResult] The fetched TokenResult
|
93
102
|
def fetch
|
94
|
-
|
95
|
-
|
103
|
+
RETRY_ATTEMPTS.times do |i|
|
104
|
+
resp = @stub.get_auth_token(Stately::Auth::GetAuthTokenRequest.new(access_key: @access_key))
|
105
|
+
return TokenResult.new(token: resp.auth_token, expires_in_secs: resp.expires_in_s)
|
106
|
+
rescue StatelyDB::Error => e
|
107
|
+
# raise if it's the final attempt or if the error is not retryable
|
108
|
+
raise e unless self.class.retryable_error?(e) && i < RETRY_ATTEMPTS - 1
|
109
|
+
|
110
|
+
# exponential backoff
|
111
|
+
sleep(backoff(i, @base_retry_backoff_secs))
|
112
|
+
end
|
96
113
|
end
|
97
114
|
|
98
115
|
def close
|
99
116
|
@channel&.close
|
100
117
|
end
|
118
|
+
|
119
|
+
# Check if an error is retryable
|
120
|
+
# @param [StatelyDB::Error] err The error to check
|
121
|
+
# @return [Boolean] True if the error is retryable
|
122
|
+
def self.retryable_error?(err)
|
123
|
+
!NON_RETRYABLE_ERRORS.include?(err.code)
|
124
|
+
end
|
101
125
|
end
|
102
126
|
end
|
103
127
|
end
|
104
128
|
end
|
129
|
+
|
130
|
+
# backoff returns a duration to wait before retrying a request. `attempt` is
|
131
|
+
# the current attempt number, starting from 0 (e.g. the first attempt is 0,
|
132
|
+
# then 1, then 2...).
|
133
|
+
#
|
134
|
+
# @param [Integer] attempt The current attempt number
|
135
|
+
# @param [Float] base_backoff The base backoff time in seconds
|
136
|
+
# @return [Float] The duration in seconds to wait before retrying
|
137
|
+
def backoff(attempt, base_backoff)
|
138
|
+
# Double the base backoff time per attempt, starting with 1
|
139
|
+
exp = 2**attempt
|
140
|
+
# Add a full jitter to the backoff time, from no wait to 100% of the exponential backoff.
|
141
|
+
# See https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
|
142
|
+
jitter = rand
|
143
|
+
(exp * jitter * base_backoff)
|
144
|
+
end
|
data/sig/statelydb.rbi
CHANGED
@@ -636,11 +636,22 @@ module StatelyDB
|
|
636
636
|
|
637
637
|
# StatelyAccessTokenFetcher is a TokenFetcher that fetches tokens from the StatelyDB API
|
638
638
|
class StatelyAccessTokenFetcher < StatelyDB::Common::Auth::TokenFetcher
|
639
|
+
NON_RETRYABLE_ERRORS = T.let([
|
640
|
+
GRPC::Core::StatusCodes::UNAUTHENTICATED,
|
641
|
+
GRPC::Core::StatusCodes::PERMISSION_DENIED,
|
642
|
+
GRPC::Core::StatusCodes::NOT_FOUND,
|
643
|
+
GRPC::Core::StatusCodes::UNIMPLEMENTED,
|
644
|
+
GRPC::Core::StatusCodes::INVALID_ARGUMENT
|
645
|
+
].freeze, T.untyped)
|
646
|
+
RETRY_ATTEMPTS = T.let(10, T.untyped)
|
647
|
+
|
639
648
|
# _@param_ `origin` — The origin of the OAuth server
|
640
649
|
#
|
641
650
|
# _@param_ `access_key` — The StatelyDB access key credential
|
642
|
-
|
643
|
-
|
651
|
+
#
|
652
|
+
# _@param_ `base_retry_backoff_secs` — The base backoff time in seconds
|
653
|
+
sig { params(origin: String, access_key: String, base_retry_backoff_secs: Float).void }
|
654
|
+
def initialize(origin:, access_key:, base_retry_backoff_secs:); end
|
644
655
|
|
645
656
|
# Fetch a new token from the StatelyDB API
|
646
657
|
#
|
@@ -650,6 +661,14 @@ module StatelyDB
|
|
650
661
|
|
651
662
|
sig { returns(T.untyped) }
|
652
663
|
def close; end
|
664
|
+
|
665
|
+
# Check if an error is retryable
|
666
|
+
#
|
667
|
+
# _@param_ `err` — The error to check
|
668
|
+
#
|
669
|
+
# _@return_ — True if the error is retryable
|
670
|
+
sig { params(err: StatelyDB::Error).returns(T::Boolean) }
|
671
|
+
def self.retryable_error?(err); end
|
653
672
|
end
|
654
673
|
|
655
674
|
# TokenProvider is an abstract base class that should be extended
|
@@ -682,16 +701,19 @@ module StatelyDB
|
|
682
701
|
# _@param_ `client_id` — The StatelyDB client ID credential
|
683
702
|
#
|
684
703
|
# _@param_ `access_key` — The StatelyDB access key credential
|
704
|
+
#
|
705
|
+
# _@param_ `base_retry_backoff_secs` — The base retry backoff in seconds
|
685
706
|
sig do
|
686
707
|
params(
|
687
708
|
origin: String,
|
688
709
|
audience: String,
|
689
710
|
client_secret: String,
|
690
711
|
client_id: String,
|
691
|
-
access_key: String
|
712
|
+
access_key: String,
|
713
|
+
base_retry_backoff_secs: Float
|
692
714
|
).void
|
693
715
|
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
|
716
|
+
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), base_retry_backoff_secs: 1); end
|
695
717
|
|
696
718
|
# Close the token provider and kill any background operations
|
697
719
|
# This just invokes the close method on the actor which should do the cleanup
|
@@ -714,16 +736,21 @@ module StatelyDB
|
|
714
736
|
# _@param_ `client_secret` — The StatelyDB client secret credential
|
715
737
|
#
|
716
738
|
# _@param_ `client_id` — The StatelyDB client ID credential
|
739
|
+
#
|
740
|
+
# _@param_ `access_key` — The StatelyDB access key credential
|
741
|
+
#
|
742
|
+
# _@param_ `base_retry_backoff_secs` — The base retry backoff in seconds
|
717
743
|
sig do
|
718
744
|
params(
|
719
745
|
origin: String,
|
720
746
|
audience: String,
|
721
747
|
client_secret: String,
|
722
748
|
client_id: String,
|
723
|
-
access_key:
|
749
|
+
access_key: String,
|
750
|
+
base_retry_backoff_secs: Float
|
724
751
|
).void
|
725
752
|
end
|
726
|
-
def initialize(origin:, audience:, client_secret:, client_id:, access_key:); end
|
753
|
+
def initialize(origin:, audience:, client_secret:, client_id:, access_key:, base_retry_backoff_secs:); end
|
727
754
|
|
728
755
|
# Initialize the actor. This runs on the actor thread which means
|
729
756
|
# we can dispatch async operations here.
|
data/sig/statelydb.rbs
CHANGED
@@ -550,10 +550,15 @@ module StatelyDB
|
|
550
550
|
|
551
551
|
# StatelyAccessTokenFetcher is a TokenFetcher that fetches tokens from the StatelyDB API
|
552
552
|
class StatelyAccessTokenFetcher < StatelyDB::Common::Auth::TokenFetcher
|
553
|
+
NON_RETRYABLE_ERRORS: untyped
|
554
|
+
RETRY_ATTEMPTS: untyped
|
555
|
+
|
553
556
|
# _@param_ `origin` — The origin of the OAuth server
|
554
557
|
#
|
555
558
|
# _@param_ `access_key` — The StatelyDB access key credential
|
556
|
-
|
559
|
+
#
|
560
|
+
# _@param_ `base_retry_backoff_secs` — The base backoff time in seconds
|
561
|
+
def initialize: (origin: String, access_key: String, base_retry_backoff_secs: Float) -> void
|
557
562
|
|
558
563
|
# Fetch a new token from the StatelyDB API
|
559
564
|
#
|
@@ -561,6 +566,13 @@ module StatelyDB
|
|
561
566
|
def fetch: () -> TokenResult
|
562
567
|
|
563
568
|
def close: () -> untyped
|
569
|
+
|
570
|
+
# Check if an error is retryable
|
571
|
+
#
|
572
|
+
# _@param_ `err` — The error to check
|
573
|
+
#
|
574
|
+
# _@return_ — True if the error is retryable
|
575
|
+
def self.retryable_error?: (StatelyDB::Error err) -> bool
|
564
576
|
end
|
565
577
|
|
566
578
|
# TokenProvider is an abstract base class that should be extended
|
@@ -591,12 +603,15 @@ module StatelyDB
|
|
591
603
|
# _@param_ `client_id` — The StatelyDB client ID credential
|
592
604
|
#
|
593
605
|
# _@param_ `access_key` — The StatelyDB access key credential
|
606
|
+
#
|
607
|
+
# _@param_ `base_retry_backoff_secs` — The base retry backoff in seconds
|
594
608
|
def initialize: (
|
595
609
|
?origin: String,
|
596
610
|
?audience: String,
|
597
611
|
?client_secret: String,
|
598
612
|
?client_id: String,
|
599
|
-
?access_key: String
|
613
|
+
?access_key: String,
|
614
|
+
?base_retry_backoff_secs: Float
|
600
615
|
) -> void
|
601
616
|
|
602
617
|
# Close the token provider and kill any background operations
|
@@ -618,12 +633,17 @@ module StatelyDB
|
|
618
633
|
# _@param_ `client_secret` — The StatelyDB client secret credential
|
619
634
|
#
|
620
635
|
# _@param_ `client_id` — The StatelyDB client ID credential
|
636
|
+
#
|
637
|
+
# _@param_ `access_key` — The StatelyDB access key credential
|
638
|
+
#
|
639
|
+
# _@param_ `base_retry_backoff_secs` — The base retry backoff in seconds
|
621
640
|
def initialize: (
|
622
641
|
origin: String,
|
623
642
|
audience: String,
|
624
643
|
client_secret: String,
|
625
644
|
client_id: String,
|
626
|
-
access_key:
|
645
|
+
access_key: String,
|
646
|
+
base_retry_backoff_secs: Float
|
627
647
|
) -> void
|
628
648
|
|
629
649
|
# Initialize the actor. This runs on the actor thread which means
|
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.15.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-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|