-
Notifications
You must be signed in to change notification settings - Fork 178
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] SendAndSubscribeTransactionStatuses endpoint implementation for Access Streaming API #5310
[Access] SendAndSubscribeTransactionStatuses endpoint implementation for Access Streaming API #5310
Conversation
…be-blocks' into guitarheroua/send-and-subscribe-transaction_statuses
…be-blocks' into guitarheroua/send-and-subscribe-transaction_statuses
…be-blocks' into guitarheroua/send-and-subscribe-transaction_statuses
…be-blocks' into guitarheroua/send-and-subscribe-transaction_statuses
…be-blocks' into guitarheroua/send-and-subscribe-transaction_statuses
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #5310 +/- ##
==========================================
+ Coverage 55.63% 56.79% +1.16%
==========================================
Files 1036 800 -236
Lines 101233 81209 -20024
==========================================
- Hits 56320 46124 -10196
+ Misses 40590 31378 -9212
+ Partials 4323 3707 -616
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
…f github.com:Guitarheroua/flow-go into guitarheroua/send-and-subscribe-transaction_statuses
…eroua/4753-local-index-tx-result
…be-blocks' into guitarheroua/send-and-subscribe-transaction_statuses
…f github.com:Guitarheroua/flow-go into guitarheroua/send-and-subscribe-transaction_statuses
…eroua/send-and-subscribe-transaction_statuses
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 don't think the logic in backendSubscribeTransactions
quite captures what's needed. I believe it will return pending until the tx is indexed, which happens after the block is sealed.
Instead of checking if we have the tx result in the local storage, check if we know which block is supposed to include the tx. this is how we do it in GetTransactionResult
https://github.com/onflow/flow-go/blob/master/engine/access/rpc/backend/backend_transactions.go#L670-L682
This will tell us that the tx is included in a finalized block. once you know the block, you can just track the block's status. After finalized, we'll wait for it to be executed. You can check that by checking for the executionResult. If one exists, the tx is executed. From executed, we just need to check if the sealed.
} | ||
|
||
if txInfo.lastTxStatus == flow.TransactionStatusSealed || txInfo.lastTxStatus == flow.TransactionStatusExpired { | ||
return nil, fmt.Errorf("transaction final status %s was already reported %w", txInfo.lastTxStatus.String(), subscription.ErrResponseNotAvailableForBlock) |
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 about returning some form of "end of data" error here. Then the subscription can just close the connection without an error if that error is encountered?
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 is the scenario I am talking about in: https://github.com/onflow/flow-go/pull/5310/files#r1530079851
This falls under consolidation of error handling for subscriptions. For this PR I would return nil, nil
and leave a TODO
to take care of it later with a proper termination logic. @peterargue thoughts?
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 challenge with nil
, nil
is it's unclear how the subscription would differentiate when a block should be skipped and when the stream should be shutdown. returning "end of data" would make it explicit
|
||
// The same transaction status should not be reported, so return here with no response | ||
if txInfo.lastTxStatus == txStatus { | ||
return nil, fmt.Errorf("transaction status %s was already reported %w", txInfo.lastTxStatus.String(), subscription.ErrResponseNotAvailableForBlock) |
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 a huge fan of using sentinels for branching between happy case scenarios, I think this return return nil, nil
and streamer should send nothing in case it sees a response like this.
@@ -21,6 +21,9 @@ import ( | |||
"github.com/onflow/flow-go/storage" | |||
) | |||
|
|||
// ErrTransactionNotInBlock represents an error indicating that the transaction is not found in the block. | |||
var ErrTransactionNotInBlock = errors.New("transaction not in block") |
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 do we need this sentinel? To me it seems we can return storage.ErrNotFound
instead of 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.
I requested this. It's because the methods used to lookup a transaction in a block need to lookup each collection in the guarantee list, then check if the transaction exists in one of the collections. Collections are synced by the Access node after the block is finalized, so it's common for there to be collections that aren't available yet when doing this lookup for non-sealed blocks.
This sentinel makes it easy for the caller to differentiate between a block that has missing collections, and one where all collections were indexed, but the tx just wasn't included.
continue | ||
} | ||
|
||
if errors.Is(err, storage.ErrNotFound) || |
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 this is where we need to take a step back and consolidate error handling. An action for a future issue.
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.
+1. In a separate PR, we should update all the other endpoints to use ErrBlockNotReady
.
access/handler.go
Outdated
subCtx, cancel := context.WithCancel(stream.Context()) | ||
defer cancel() |
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.
since we're not using cancel anymore, can you remove it
subCtx, cancel := context.WithCancel(stream.Context()) | |
defer cancel() | |
ctx := stream.Context() |
@@ -21,6 +21,9 @@ import ( | |||
"github.com/onflow/flow-go/storage" | |||
) | |||
|
|||
// ErrTransactionNotInBlock represents an error indicating that the transaction is not found in the block. | |||
var ErrTransactionNotInBlock = errors.New("transaction not in block") |
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 requested this. It's because the methods used to lookup a transaction in a block need to lookup each collection in the guarantee list, then check if the transaction exists in one of the collections. Collections are synced by the Access node after the block is finalized, so it's common for there to be collections that aren't available yet when doing this lookup for non-sealed blocks.
This sentinel makes it easy for the caller to differentiate between a block that has missing collections, and one where all collections were indexed, but the tx just wasn't 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.
added a couple small comments, but otherwise looks good.
continue | ||
} | ||
|
||
if errors.Is(err, storage.ErrNotFound) || |
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.
+1. In a separate PR, we should update all the other endpoints to use ErrBlockNotReady
.
s.Assert().Equal(txID, sdk.Identifier(resp.GetId())) | ||
|
||
expectedCounter++ | ||
finalTxStatus = resp.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.
can you have it also check that it receives notifications for each of the statuses in the processes
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 was checked, and it returns the next pattern "Pending"->"Finalized"->"Sealed". Should return all the statuses including "Executed", as agreed, this will be done in the next iteration, when this endpoint will be expanded with TX 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.
Ready to go
Co-authored-by: Yurii Oleksyshyn <[email protected]>
Implementation of
SendAndSubscribeTransactionStatuses
endpoint for Access Streaming API.Depends on: onflow/flow-emulator#613
FLIP: onflow/flips#229