@@ -18,10 +18,13 @@ limitations under the License.
18
18
package throttle
19
19
20
20
import (
21
+ "context"
21
22
"regexp"
22
23
"strings"
23
24
25
+ awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
24
26
"github.com/aws/aws-sdk-go/aws/request"
27
+ "github.com/aws/smithy-go/middleware"
25
28
26
29
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/awserrors"
27
30
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/internal/rate"
@@ -52,6 +55,11 @@ func (o *OperationLimiter) Wait(r *request.Request) error {
52
55
return o .getLimiter ().Wait (r .Context ())
53
56
}
54
57
58
+ // WaitV2 will wait on a request for AWS SDK V2.
59
+ func (o * OperationLimiter ) WaitV2 (ctx context.Context ) error {
60
+ return o .getLimiter ().Wait (ctx )
61
+ }
62
+
55
63
// Match will match a request.
56
64
func (o * OperationLimiter ) Match (r * request.Request ) (bool , error ) {
57
65
if o .regexp == nil {
@@ -64,13 +72,33 @@ func (o *OperationLimiter) Match(r *request.Request) (bool, error) {
64
72
return o .regexp .MatchString (r .Operation .Name ), nil
65
73
}
66
74
75
+ // MatchV2 will match a request for AWS SDK V2.
76
+ func (o * OperationLimiter ) MatchV2 (ctx context.Context ) (bool , error ) {
77
+ if o .regexp == nil {
78
+ var err error
79
+ o .regexp , err = regexp .Compile ("^" + o .Operation )
80
+ if err != nil {
81
+ return false , err
82
+ }
83
+ }
84
+ opName := awsmiddleware .GetOperationName (ctx )
85
+ return o .regexp .MatchString (opName ), nil
86
+ }
87
+
67
88
// LimitRequest will limit a request.
68
89
func (s ServiceLimiter ) LimitRequest (r * request.Request ) {
69
90
if ol , ok := s .matchRequest (r ); ok {
70
91
_ = ol .Wait (r )
71
92
}
72
93
}
73
94
95
+ // LimitRequestV2 will limit a request for AWS SDK V2.
96
+ func (s ServiceLimiter ) LimitRequestV2 (ctx context.Context ) {
97
+ if ol , ok := s .matchRequestV2 (ctx ); ok {
98
+ _ = ol .WaitV2 (ctx )
99
+ }
100
+ }
101
+
74
102
func (o * OperationLimiter ) getLimiter () * rate.Limiter {
75
103
if o .limiter == nil {
76
104
o .limiter = rate .NewLimiter (o .RefillRate , o .Burst )
@@ -92,6 +120,16 @@ func (s ServiceLimiter) ReviewResponse(r *request.Request) {
92
120
}
93
121
}
94
122
123
+ // ReviewResponseV2 will review the limits of a Request's response for AWS SDK V2.
124
+ func (s ServiceLimiter ) ReviewResponseV2 (ctx context.Context , errorCode string ) {
125
+ switch errorCode {
126
+ case "Throttling" , "RequestLimitExceeded" :
127
+ if ol , ok := s .matchRequestV2 (ctx ); ok {
128
+ ol .limiter .ResetTokens ()
129
+ }
130
+ }
131
+ }
132
+
95
133
func (s ServiceLimiter ) matchRequest (r * request.Request ) (* OperationLimiter , bool ) {
96
134
for _ , ol := range s {
97
135
match , err := ol .Match (r )
@@ -104,3 +142,37 @@ func (s ServiceLimiter) matchRequest(r *request.Request) (*OperationLimiter, boo
104
142
}
105
143
return nil , false
106
144
}
145
+
146
+ // matchRequestV2 is used for matching request for AWS SDK V2.
147
+ func (s ServiceLimiter ) matchRequestV2 (ctx context.Context ) (* OperationLimiter , bool ) {
148
+ for _ , ol := range s {
149
+ match , err := ol .MatchV2 (ctx )
150
+ if err != nil {
151
+ return nil , false
152
+ }
153
+ if match {
154
+ return ol , true
155
+ }
156
+ }
157
+ return nil , false
158
+ }
159
+
160
+ // WithServiceLimiterMiddleware returns ServiceLimiter middleware stack for specified service name.
161
+ func WithServiceLimiterMiddleware (limiter * ServiceLimiter ) func (stack * middleware.Stack ) error {
162
+ return func (stack * middleware.Stack ) error {
163
+ // Inserts service Limiter middleware after RequestContext initialization.
164
+ return stack .Finalize .Insert (getServiceLimiterMiddleware (limiter ), "capa/RequestMetricContextMiddleware" , middleware .After )
165
+ }
166
+ }
167
+
168
+ // getServiceLimiterMiddleware implements serviceLimiter middleware.
169
+ func getServiceLimiterMiddleware (limiter * ServiceLimiter ) middleware.FinalizeMiddleware {
170
+ return middleware .FinalizeMiddlewareFunc ("capa/ServiceLimiterMiddleware" , func (ctx context.Context , input middleware.FinalizeInput , handler middleware.FinalizeHandler ) (middleware.FinalizeOutput , middleware.Metadata , error ) {
171
+ limiter .LimitRequestV2 (ctx )
172
+
173
+ out , metadata , err := handler .HandleFinalize (ctx , input )
174
+ smithyErr := awserrors .ParseSmithyError (err )
175
+ limiter .ReviewResponseV2 (ctx , smithyErr .ErrorCode ())
176
+ return out , metadata , err
177
+ })
178
+ }
0 commit comments