Skip to content

Commit 6221102

Browse files
authored
fix stale skew and delayed skew healing (#3359)
* fix stale skew * fix comment * fix test * delete old test which is now covered in kitchensink * regen after rebase * add no-retry test * regenerate
1 parent 0a39373 commit 6221102

File tree

36,963 files changed

+19775
-113763
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

36,963 files changed

+19775
-113763
lines changed

.changelog/9f49dccb1c42499f9a39521bea5bc73b.json

Lines changed: 426 additions & 0 deletions
Large diffs are not rendered by default.

aws/retry/middleware.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"strconv"
88
"strings"
9+
"sync/atomic"
910
"time"
1011

1112
internalcontext "github.com/aws/aws-sdk-go-v2/internal/context"
@@ -43,6 +44,10 @@ type Attempt struct {
4344
// A Meter instance for recording retry-related metrics.
4445
OperationMeter metrics.Meter
4546

47+
// Initial clock skew that would have been saved from a previous operation
48+
// call.
49+
ClientSkew *atomic.Int64
50+
4651
retryer aws.RetryerV2
4752
requestCloner RequestCloner
4853
}
@@ -82,8 +87,12 @@ func (r Attempt) logf(logger logging.Logger, classification logging.Classificati
8287
func (r *Attempt) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeInput, next smithymiddle.FinalizeHandler) (
8388
out smithymiddle.FinalizeOutput, metadata smithymiddle.Metadata, err error,
8489
) {
85-
var attemptNum int
8690
var attemptClockSkew time.Duration
91+
if r.ClientSkew != nil {
92+
attemptClockSkew = time.Duration(r.ClientSkew.Load())
93+
}
94+
95+
var attemptNum int
8796
var attemptResults AttemptResults
8897

8998
maxAttempts := r.retryer.MaxAttempts()
@@ -99,6 +108,8 @@ func (r *Attempt) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeIn
99108
attemptInput := in
100109
attemptInput.Request = r.requestCloner(attemptInput.Request)
101110

111+
ctx = internalcontext.SetAttemptSkewContext(ctx, attemptClockSkew)
112+
102113
// Record the metadata for the for attempt being started.
103114
attemptCtx := setRetryMetadata(ctx, retryMetadata{
104115
AttemptNum: attemptNum,
@@ -107,9 +118,6 @@ func (r *Attempt) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeIn
107118
AttemptClockSkew: attemptClockSkew,
108119
})
109120

110-
// Setting clock skew to be used on other context (like signing)
111-
ctx = internalcontext.SetAttemptSkewContext(ctx, attemptClockSkew)
112-
113121
var attemptResult AttemptResult
114122

115123
attemptCtx, span := tracing.StartSpan(attemptCtx, "Attempt", func(o *tracing.SpanOptions) {
@@ -149,6 +157,14 @@ func (r *Attempt) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeIn
149157
}
150158
}
151159

160+
// this guarantees we are staying on top of the persistent skew value
161+
// (either to apply it or to heal it back if the clocks realign)
162+
if r.ClientSkew != nil {
163+
if resultSkew, ok := awsmiddle.GetAttemptSkew(metadata); ok {
164+
r.ClientSkew.Store(resultSkew.Nanoseconds())
165+
}
166+
}
167+
152168
addAttemptResults(&metadata, attemptResults)
153169
return out, metadata, err
154170
}

aws/retry/middleware_test.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@ import (
88
"reflect"
99
"strconv"
1010
"strings"
11+
"sync/atomic"
1112
"testing"
1213
"time"
1314

14-
internalcontext "github.com/aws/aws-sdk-go-v2/internal/context"
15-
1615
"github.com/aws/aws-sdk-go-v2/aws/ratelimit"
1716
"github.com/aws/aws-sdk-go-v2/internal/sdk"
1817
"github.com/aws/smithy-go/middleware"
@@ -531,9 +530,13 @@ func TestClockSkew(t *testing.T) {
531530
}
532531
for name, tt := range cases {
533532
t.Run(name, func(t *testing.T) {
533+
skew := &atomic.Int64{}
534+
skew.Store(tt.skew.Nanoseconds())
534535
am := NewAttemptMiddleware(NewStandard(func(s *StandardOptions) {
535-
}), func(i any) any { return i })
536-
ctx := internalcontext.SetAttemptSkewContext(context.Background(), tt.skew)
536+
}), func(i any) any { return i }, func(m *Attempt) {
537+
m.ClientSkew = skew
538+
})
539+
ctx := context.Background()
537540
_, metadata, err := am.HandleFinalize(ctx, middleware.FinalizeInput{}, middleware.FinalizeHandlerFunc(
538541
func(ctx context.Context, in middleware.FinalizeInput) (
539542
out middleware.FinalizeOutput, metadata middleware.Metadata, err error,

codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/AssembleMiddlewareStack.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,10 @@ public List<RuntimeClientPlugin> getClientPlugins() {
154154
.resolvedFunction(SymbolUtils.createValueSymbolBuilder(
155155
AwsRetryMiddlewareHelper.ADD_RETRY_MIDDLEWARES_HELPER)
156156
.build())
157-
.useClientOptions()
157+
.functionArguments(List.of(
158+
buildPackageSymbol("options"),
159+
buildPackageSymbol("c")
160+
))
158161
.build())
159162
.build(),
160163

codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/AwsRetryMiddlewareHelper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ private void generateRetryMiddlewareHelpers(GoWriter writer, String moduleName)
4545
.addUseImports(SmithyGoDependency.SMITHY_HTTP_TRANSPORT)
4646
.addUseImports(AwsGoDependency.AWS_RETRY)
4747
.write(goTemplate("""
48-
func addRetry(stack *middleware.Stack, o Options) error {
48+
func addRetry(stack *middleware.Stack, o Options, c *Client) error {
4949
attempt := retry.NewAttemptMiddleware(o.Retryer, smithyhttp.RequestCloner, func(m *retry.Attempt) {
5050
m.LogAttempts = o.ClientLogMode.IsRetries()
5151
m.OperationMeter = o.MeterProvider.Meter($S)
52+
m.ClientSkew = c.timeOffset
5253
})
5354
if err := stack.Finalize.Insert(attempt, "ResolveAuthScheme", middleware.Before); err != nil {
5455
return err

codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/ClockSkewGenerator.java

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,31 +21,10 @@
2121
*/
2222
public class ClockSkewGenerator implements GoIntegration {
2323
private static final String TIME_OFFSET = "timeOffset";
24-
private static final String ADD_CLOCK_SKEW_BUILD = "addTimeOffsetBuild";
25-
private static final String ADD_CLOCK_SKEW_BUILD_MIDDLEWARE = "AddTimeOffsetMiddleware";
2624

2725
private static final Symbol TIME_OFFSET_RESOLVER = SymbolUtils.createValueSymbolBuilder(
2826
"initializeTimeOffsetResolver").build();
2927

30-
private static final Writable CLOCK_SKEW_INSERT_TEMPLATE = goTemplate("""
31-
$dep:D
32-
func $fn:L(stack $stack:P, c *Client) error {
33-
mw := $depalias:L.$middleware:L{Offset: c.$off:L}
34-
if err := stack.Build.Add(&mw, middleware.After); err != nil {
35-
return err
36-
}
37-
return stack.Deserialize.Insert(&mw, "$after:L", middleware.Before)
38-
}
39-
""",
40-
Map.of(
41-
"fn", ADD_CLOCK_SKEW_BUILD,
42-
"stack", SmithyGoDependency.SMITHY_MIDDLEWARE.struct("Stack"),
43-
"depalias", INTERNAL_MIDDLEWARE.getAlias(),
44-
"middleware", ADD_CLOCK_SKEW_BUILD_MIDDLEWARE,
45-
"after", "RecordResponseTiming",
46-
"off", TIME_OFFSET,
47-
"dep", INTERNAL_MIDDLEWARE
48-
));
4928
private static final Writable TIME_OFFSET_RESOLVER_TEMPLATE = goTemplate(
5029
"""
5130
$import:D
@@ -68,16 +47,10 @@ public class ClockSkewGenerator implements GoIntegration {
6847
private static final ClientMemberResolver TIME_OFFSET_MEMBER_RESOLVER = ClientMemberResolver.builder()
6948
.resolver(TIME_OFFSET_RESOLVER)
7049
.build();
71-
private static final MiddlewareRegistrar MIDDLEWARE = MiddlewareRegistrar.builder()
72-
.resolvedFunction(SymbolUtils.createValueSymbolBuilder(ADD_CLOCK_SKEW_BUILD).build())
73-
.functionArguments(ListUtils.of(
74-
SymbolUtils.createValueSymbolBuilder("c").build()
75-
)).build();
7650
private static final List<RuntimeClientPlugin> CLIENT_PLUGINS = List.of(
7751
RuntimeClientPlugin.builder()
7852
.addClientMember(TIME_OFFSET_MEMBER)
7953
.addClientMemberResolver(TIME_OFFSET_MEMBER_RESOLVER)
80-
.registerMiddleware(MIDDLEWARE)
8154
.build()
8255
);
8356

@@ -93,7 +66,6 @@ public void writeAdditionalFiles(
9366

9467
// generate code specific to service client
9568
goDelegator.useShapeWriter(service, writer -> {
96-
writer.write(CLOCK_SKEW_INSERT_TEMPLATE);
9769
writer.write(TIME_OFFSET_RESOLVER_TEMPLATE);
9870
});
9971
}
@@ -102,4 +74,4 @@ public void writeAdditionalFiles(
10274
public List<RuntimeClientPlugin> getClientPlugins() {
10375
return CLIENT_PLUGINS;
10476
}
105-
}
77+
}

internal/kitchensinktest/api_client.go

Lines changed: 2 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/kitchensinktest/api_op_GetItem.go

Lines changed: 1 addition & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)