-
Notifications
You must be signed in to change notification settings - Fork 30
[ECR-2914] LC: Implemented get transaction endpoint support #725
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
import com.google.gson.JsonSerializer; | ||
import java.lang.reflect.Type; | ||
|
||
final class TransactionMessageJsonSerializer implements JsonSerializer<TransactionMessage>, |
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.
Are there any needs for TransactionMessage
serialization to JSON in other ways?
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.
Can't say 🤷♂️ @vitvakatu , @MakarovS ?
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'd leave it as it is for now.
@@ -32,8 +30,6 @@ | |||
* if execution has failed. | |||
* Errors might be either service-defined or unexpected. Service-defined errors consist of an error | |||
* code and an optional description. Unexpected errors include only a description. | |||
* | |||
* @see TransactionExecutionException |
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 link becomes broken because TransactionExecutionException
locates in the core module.
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 see, would you add a back reference to TransactionExecutionException, if there isn't one already?
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 added a reference at TransactionExecutionException
to this 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.
👍
if (response.code() == HTTP_NOT_FOUND) { | ||
return Optional.empty(); | ||
} else if (!response.isSuccessful()) { | ||
throw new RuntimeException("Execution wasn't success: " + response.toString()); |
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.
Either successful
or a success
private String blockingExecutePlainText(Request request) { | ||
return blockingExecute(request, response -> { | ||
if (!response.isSuccessful()) { | ||
throw new RuntimeException("Execution wasn't success: " + response.toString()); |
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.
Same here
} else if (executionStatus.getType() == GetTxResponseExecutionStatus.ERROR) { | ||
return TransactionResult.error(executionStatus.getCode(), executionStatus.getDescription()); | ||
} else { | ||
throw new IllegalArgumentException("Unexpected transaction execution status" |
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.
Some delimiter at the end?
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, thanks 👍
I'd ponder on some questions/suggestions below.
.registerTypeAdapter(PublicKey.class, new PublicKeyJsonSerializer()) | ||
.registerTypeAdapterFactory(StoredConfigurationAdapterFactory.create()) | ||
.setLongSerializationPolicy(LongSerializationPolicy.STRING); | ||
.setLongSerializationPolicy(LongSerializationPolicy.STRING) |
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'd possibly group related things together (type adapters, then long serialization policy, or vice-versa).
@@ -32,8 +30,6 @@ | |||
* if execution has failed. | |||
* Errors might be either service-defined or unexpected. Service-defined errors consist of an error | |||
* code and an optional description. Unexpected errors include only a description. | |||
* | |||
* @see TransactionExecutionException |
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 see, would you add a back reference to TransactionExecutionException, if there isn't one already?
} | ||
|
||
@Test | ||
void transactionMessageSerializesAsValue() { |
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.
Shan't we make round-trip tests?
There is one below.
@ParameterizedTest | ||
@MethodSource("source") | ||
void roundTripTest(TransactionMessage msg) { | ||
String json = json().toJson(msg); |
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 test relies on the fact that JsonSerializer includes a TransactionMessage adapter, correct? Shan't we use Gson here directly? Or move this test to JsonSerializerTest? I'd prefer to keep it here, separate.
String getUserAgentInfo(); | ||
|
||
/** | ||
* Returns transaction with current status. Or {@code Optional.empty()} if |
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.
Returns the information about the transaction; or {@code Optional.empty()} if ?
?
byte[] actualMessageBytes = HEX_ENCODER.decode(encodedTxMessage); | ||
TransactionMessage actualTxMessage = TransactionMessage.fromBytes(actualMessageBytes); | ||
|
||
assertThat(actualTxMessage, is(txMessage)); |
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.
Don't we longer check that we sent a properly encoded transaction?
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 rely on Gson
instance here. But I agree, let's have some checks in case of regression.
} | ||
|
||
@Test | ||
void getTransactionNotFound() throws InterruptedException { |
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.
Shan't we add a happy result?
TransactionResponse transactionResponse = ExplorerApiHelper.parseGetTxResponse(json); | ||
|
||
assertThat(transactionResponse.getStatus(), is(TransactionStatus.IN_POOL)); | ||
assertThat(transactionResponse.getMessage(), notNullValue()); |
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.
Shan't we extract the message as a constant and assert that we get exactly that?
@NonNull | ||
TransactionMessage message; | ||
/** | ||
* Transaction execution result; {@code null} - for in-pool transactions. |
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 we define the getter that throws IllegalStateE
instead? That will roughly align the behaviour of this class with Optional
.
Alternatively we can return Optional<TransactionResult|TransactionLocation>
, but in that case the clients who have checked the status would be penalized with an additional ifPresent/isPresent + get
.
What do you think would be more convenient:
null
Optional
- not-
null
with a required check of the status?
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.
By going with the third approach you will also need to check the status before calling getter. Only one thing that can be considered as a proc (comparing with the first approach) is to have some error description instead of NPE
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.
That's not one thing:
- You get an error early, rather than in undefined time range. And yes, it has an error description.
- There is a clear connection between the tx status and possible absence of a value — you don't have to check both values for
null
s "just in case" if you have checked if the transaction is committed.
import com.google.gson.JsonSerializer; | ||
import java.lang.reflect.Type; | ||
|
||
final class TransactionMessageJsonSerializer implements JsonSerializer<TransactionMessage>, |
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.
Can't say 🤷♂️ @vitvakatu , @MakarovS ?
return TransactionResult.successful(); | ||
} else if (executionStatus.getType() == GetTxResponseExecutionStatus.ERROR) { | ||
return TransactionResult.error(executionStatus.getCode(), executionStatus.getDescription()); | ||
} else if (executionStatus.getType() == GetTxResponseExecutionStatus.PANIC) { |
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.
Is there a test for that?
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.
added
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'd also consider adding isCommitted
* @throws IllegalStateException if the transaction is not committed yet | ||
*/ | ||
public TransactionResult getExecutionResult() { | ||
checkState(status == COMMITTED, |
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 think we must add such a convenience method if we require the clients to check for transaction status:
/**
* Returns true if this transaction is {@linkplain TransactionStatus#COMMITTED committed} to the blockchain;
* false — otherwise.
*/
boolean isCommitted();
TransactionLocation location; | ||
|
||
/** | ||
* Returns transaction execution result. |
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.
+ Not available unless the transaction is {@linkplain #isCommitted committed} to the blockchain
?
@SerializedName("in-pool") | ||
IN_POOL, | ||
/** | ||
* Shows that transaction is committed to the blockchain. |
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.
+
Please note that a committed transaction has not necessarily completed
successfully — use the {@linplain TransactionResult execution result}
to check that.
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.
💯
Looks great (but check please if changelog needs to be updated)
Overview
See: https://jira.bf.local/browse/ECR-2914
TransactionResult
moved to the common module.TransactionLocation
moved to the common module.TransactionMessage
.Definition of Done