-
Notifications
You must be signed in to change notification settings - Fork 966
Add verifications of ClientRequestContext
s to RetryClientTest
and RetryingRpcClientTest
#6296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add verifications of ClientRequestContext
s to RetryClientTest
and RetryingRpcClientTest
#6296
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6296 +/- ##
============================================
+ Coverage 74.46% 74.56% +0.10%
- Complexity 22234 22611 +377
============================================
Files 1963 2022 +59
Lines 82437 83734 +1297
Branches 10764 10866 +102
============================================
+ Hits 61385 62439 +1054
- Misses 15918 16094 +176
- Partials 5134 5201 +67 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
ClientRequestContext
s to RetryClientTest
ClientRequestContext
s to RetryClientTest
and RetryingRpcClientTest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate the additional validation in retrying tests. I've reviewed mainly RequestContextUtils
mainly considering how we can use this utility more extensively within the code-base.
if (childLogVerifiers.length == 0) { | ||
childLogVerifiers = new RequestLogVerifier[ctx.log().children().size()]; | ||
Arrays.fill(childLogVerifiers, VERIFY_NOTHING); | ||
} | ||
|
||
assertValidRequestContextWithVerifier( | ||
ctx, | ||
childLogVerifiers.length == 0 ? | ||
VERIFY_NOTHING | ||
: verifyAllValid( | ||
childLog -> { | ||
// Default parent log verifier. | ||
final HttpRequest req = ctx.request(); | ||
assertThat(req).isNotNull(); | ||
assert req != null; | ||
assertThat(req.isComplete()).isTrue(); | ||
|
||
if (ctx.rpcRequest() != null) { | ||
final HttpRequest lastHttpReq = | ||
ctx.log().children() | ||
.get(ctx.log().children().size() - 1).context().request(); | ||
|
||
if (lastHttpReq != null) { | ||
assertThat(lastHttpReq).isSameAs(ctx.log().context().request()); | ||
} | ||
} | ||
}, | ||
childLogVerifiers[childLogVerifiers.length - 1] | ||
), childLogVerifiers | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question) I was a little surprised this validation only exists in this overriding variant. Would it make sense that this method simply calls assertValidRequestContextWithVerifier
without the parent verifier?
Can the lastHttpReq
check be included in the method at L180, or provided as a separate verifyLastChildHasSameHttpRequest()
verifier if necessary?
e.g.
if (childLogVerifiers.length == 0) { | |
childLogVerifiers = new RequestLogVerifier[ctx.log().children().size()]; | |
Arrays.fill(childLogVerifiers, VERIFY_NOTHING); | |
} | |
assertValidRequestContextWithVerifier( | |
ctx, | |
childLogVerifiers.length == 0 ? | |
VERIFY_NOTHING | |
: verifyAllValid( | |
childLog -> { | |
// Default parent log verifier. | |
final HttpRequest req = ctx.request(); | |
assertThat(req).isNotNull(); | |
assert req != null; | |
assertThat(req.isComplete()).isTrue(); | |
if (ctx.rpcRequest() != null) { | |
final HttpRequest lastHttpReq = | |
ctx.log().children() | |
.get(ctx.log().children().size() - 1).context().request(); | |
if (lastHttpReq != null) { | |
assertThat(lastHttpReq).isSameAs(ctx.log().context().request()); | |
} | |
} | |
}, | |
childLogVerifiers[childLogVerifiers.length - 1] | |
), childLogVerifiers | |
); | |
assertValidRequestContextWithVerifier(ctx,VERIFY_NOTHING, childLogVerifiers); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are situations where the caller wants to override the default parent log verifier so that is why it was only at that place and not integrated further dowstream.
I reflected on this and I think it is best to extract those checks into separate verifiers as you said and just always demand from the caller to provide a parent log verifier. The advantage of that is that the test are then more explicit on what to expect from the parent log which is less given with a hidden default parent log verifier.
|
||
@FunctionalInterface | ||
public interface RequestLogVerifier { | ||
void verifyChildLog(RequestLog childLog) throws Exception; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit; I wonder if it makes sense to drop the child prefix since the validation can also be applied to the parent log.
void verifyChildLog(RequestLog childLog) throws Exception; | |
void verifyLog(RequestLog requestLog) throws Exception; |
}; | ||
} | ||
|
||
public static RequestLogVerifier verifyExactlyOneValid(RequestLogVerifier... childLogVerifiers) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just me, but I was imagining exactly one child is valid for all of the verifiers when looking at the name
public static RequestLogVerifier verifyExactlyOneValid(RequestLogVerifier... childLogVerifiers) { | |
public static RequestLogVerifier verifyExactlyOneVerifierValid(RequestLogVerifier... childLogVerifiers) { |
if (expectedNumRequests == 0) { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question) What do you think of removing this restriction? I still think this method can be useful in validating parentLogVerifier
final WebClient client = client(rule, | ||
10000, 0, 100); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit;
final WebClient client = client(rule, | |
10000, 0, 100); | |
final WebClient client = client(rule, 10000, 0, 100); |
@jrhee17 Thank you for the review 🤙 . I addressed your comments. I am not sure if you like me to close the comments myself or leave them open. Feel free to educate me if there some Armeria-wide convention for this |
Motivation:
RetryingClientTest
andRetryingRpcClientTest
validate the respective retrying clients under various (failure) conditions.However, not all test cases check whether the client-side request log is properly propagated by the client, e.g., whether:
Verifying the logs becomes even more important for #6252, where the retrying client must ensure it properly completes concurrent pending requests—either when a response is received or when a request fails unrecoverably, thereby also failing all other pending requests. Aforementioned tests would increase our confidence that the upcoming hedging client does not cause regressions.
Modifications:
All changes are test-only.
RequestContextUtils
) for verifyingClientRequestContext
s, especially the log, in a concise way.RetryingClientTest
andRetryingRpcClientTest
by incorporating verifications using that utility class.Result:
ClientRequestContext
under various failure scenarios.RequestContextUtils
now helps in writing concise tests that validateClientRequestContext
, e.g., for request hedging.