Skip to content
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

[Access] Improvements for SubscribeTransactionStatuses statuses handling #6736

Open
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

Guitarheroua
Copy link
Contributor

@Guitarheroua Guitarheroua commented Nov 19, 2024

Closes #6574

Updated the logic for checking transaction results. The system now always checks local storage first, and if no transaction result is found, it attempts to retrieve it from the execution node.

@codecov-commenter
Copy link

codecov-commenter commented Nov 19, 2024

Codecov Report

Attention: Patch coverage is 90.00000% with 2 lines in your changes missing coverage. Please review.

Project coverage is 41.12%. Comparing base (219660a) to head (40a3323).

Files with missing lines Patch % Lines
.../access/rpc/backend/backend_stream_transactions.go 94.44% 1 Missing ⚠️
engine/access/rpc/backend/backend_transactions.go 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6736       /-   ##
==========================================
- Coverage   41.12%   41.12%   -0.01%     
==========================================
  Files        2107     2107              
  Lines      185330   185326       -4     
==========================================
- Hits        76220    76217       -3     
  Misses     102710   102708       -2     
- Partials     6400     6401        1     
Flag Coverage Δ
unittests 41.12% <90.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@Guitarheroua Guitarheroua self-assigned this Nov 20, 2024
@Guitarheroua Guitarheroua marked this pull request as ready for review November 21, 2024 07:42
Copy link
Contributor

@peterargue peterargue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this also address #6778?

@Guitarheroua
Copy link
Contributor Author

Guitarheroua commented Dec 4, 2024

does this also address #6778?

Yes, this PR should close #6778 as well, as we will always try to get a result from the execution node if it is not synced yet.

Copy link
Contributor

@peterargue peterargue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks good. have you tried it on localnet?

@Guitarheroua
Copy link
Contributor Author

this looks good. have you tried it on localnet?

Nope, just run tests. I will check it on the localnet.

@peterargue peterargue requested a review from durkmurder January 2, 2025 17:55
@@ -36,7 36,7 @@ type backendSubscribeTransactions struct {
type TransactionSubscriptionMetadata struct {
*access.TransactionResult
txReferenceBlockID flow.Identifier
blockWithTx *flow.Header
blockWithTx *flow.Block
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have checked underlying code path and couldn't find a place why we essentially need a flow.Block. My suggestion here would be to stick to flow.Header and actually refactor usages of this field to accept flow.Header instead of flow.Block. I think that we should carry only the minimal needed information since extra info increases mental complexity and makes the APIs more convoluted and less intuitive.
Suppose I see a method signature:

GetTransactionResultFromExecutionNode(ctx context.Context,
	block *flow.Block,
	transactionID flow.Identifier,
	requiredEventEncodingVersion entities.EventEncodingVersion)

when I see such signature I assume that it does something with the block payload since it passes a block rather than a header and the difference between block and header is exactly the payload, in fact it is misleading since it utilizes only fields of flow.Header. To avoid such misleading APIs I would propose to make a refactoring to clean this.

func (b *backendSubscribeTransactions) searchForTransactionResult(
ctx context.Context,
txInfo *TransactionSubscriptionMetadata,
) (*access.TransactionResult, error) {
_, err := b.executionResults.ByBlockID(txInfo.BlockID)
txResult, err := b.backendTransactions.GetTransactionResultFromStorage(ctx, txInfo.blockWithTx, txInfo.TransactionID, txInfo.eventEncodingVersion)
if err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at this point you can receive multiple sentinel errors and I assume an exception as well. We are basically sweeping all errors under one if statement but I would suggest to explicitly filter if it's an expected error. Otherwise we might get into a situation where a node observes a critical failure(lets say a storage failure where the badger DB is corrupted) but we are still trying to operate on best-effort scenario which is unacceptable.

txInfo.CollectionID,
txInfo.eventEncodingVersion,
)
// If any error occurs with local storage - request transaction result from EN
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as I said in previously comment, "any" error is a bit to extreme

// if either the execution node reported no results
if status.Code(err) == codes.NotFound {
// No result yet, indicate that it has not been executed
return nil, nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This convention is not explained in the documentation, usually if there is no error then a result has to be available, returning nil, nil is undesirable, I am leaning to updating the documentation and returning a sentinel error to inform caller that there is no data available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Access] Improve SendAndSubscribe status handling
4 participants