-
Notifications
You must be signed in to change notification settings - Fork 181
Renamed EncodedValue to EncodedValues to support multiple details #164
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
Conversation
mfateev
commented
Jul 31, 2020
- Updated DataConverter API to support extracting individual values from the serialized list.
- Renamed EncodedValue to EncodedValues.
- Added ApplicationFailure factories for clarity.
| Type[] genericParameterTypes) | ||
| throws DataConverterException { | ||
| if (parameterTypes != null | ||
| && (parameterTypes == null || parameterTypes.length != genericParameterTypes.length)) { |
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.
the first clause of this condition checks that parameterTypes is not null, so this parameterTypes==null check is unnecessary, right? Or did you mean to check if genericParameterTypes is null?
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.
good catch!
| for (int i = 0; i < parameterTypes.length; i++) { | ||
| Class<?> pt = parameterTypes[i]; | ||
| Type gt = genericParameterTypes[i]; | ||
| if (i >= count) { |
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.
what if the count of payloads is much greater than that of the parameters? Basically does the user need to know that they are missing out on some payloads? Or is this well understood?
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.
Good question. The current answer is that it is needed to be able to add and remove arguments of functions.
| } else { | ||
| if (converter == null) { | ||
| throw new IllegalStateException("converter not set"); | ||
| if (payloads.isPresent()) { |
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.
we are guaranteed that at least one of values / payloads is not null right? Basically, values and payloads cannot both be null because (Object... values) guarantees values is at least of length 0 if that constructor is used?
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.
In a lot of cases, Payloads are not set at all if there are no any values. But we probably need to audit for this.
| if (converter == null) { | ||
| throw new IllegalStateException("converter not set"); | ||
| } | ||
| return converter.fromPayloads(index, payloads, parameterType, genericParameterType); |
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.
No need to initialize / cache the converted object into the values array right?
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.
The idea of Values is that it can be created with objects or Payloads. I'm not sure if caching is really going to help here as every value accessed only once I believe.
| private boolean nonRetryable; | ||
|
|
||
| /** | ||
| * New ApplicationFailure with {@link #isNonRetryable()} flag set to false. Note that this |
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.
didn't quite follow the 2nd sentence of this comment. did you mean to say if the type is NOT included
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.
Good catch.
| */ | ||
| public ApplicationFailure(String message, String type, Object details, Exception cause) { | ||
| this(message, type, new EncodedValue(details), false, cause); | ||
| public static ApplicationFailure newFailure(String message, String type, Object... details) { |
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.
why not just call it newRetryableFailure?
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 called it initially. But then I found that it is very confusing that it can be not retried if the policy says so.
| public ApplicationFailure(String message) { | ||
| this(message, null); | ||
| static ApplicationFailure newFromValues( | ||
| String message, String type, boolean nonRetryable, Values details, Throwable cause) { |
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], having boolean names that are negative (nonRetryable vs retryable) can be kind of confusing
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 almost always follow the pattern that the default value should be the default value for the type. So the default of the boolean type is false. So the field is called nonRetryable as its default is false. But I agree that it looks weird in the parameter name.
| } | ||
| Optional<Payloads> details = info.getHeartbeatDetails(); | ||
| return Optional.ofNullable(dataConverter.fromPayloads(details, detailsClass, detailsType)); | ||
| return Optional.ofNullable(dataConverter.fromPayloads(0, details, detailsClass, detailsType)); |
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.
we didn't want this function to have an overload without the index that internally assumes the first element? seems painful to pass in 0 every time
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.
This class is used only internally by the SDK, so I think having an explicit index makes sense to indicate that it can hold multiple values.
| assertEquals("foo", ((ApplicationFailure) e.getCause()).getType()); | ||
| assertEquals("details", ((ApplicationFailure) e.getCause()).getDetails().get(String.class)); | ||
| assertEquals( | ||
| "details1", ((ApplicationFailure) e.getCause()).getDetails().get(0, String.class)); |
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.
and we still have a test that validates get without the index specified works fine?
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 checked and found at least two unit tests that call it.
| return converter.fromPayloads(payloads, parameterType, genericParameterType); | ||
| if (values != null) { | ||
| @SuppressWarnings("unchecked") | ||
| T result = (T) values[index]; |
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.
if the user exceeds the bounds of the values/payload, no issues right?