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

services/horizon: add option to submit without waiting for transaction final state #3564

Closed
wants to merge 2 commits into from

Conversation

leighmcculloch
Copy link
Member

PR Checklist

PR Structure

  • This PR has reasonably narrow scope (if not, break it down into smaller PRs).
  • This PR avoids mixing refactoring changes with feature changes (split into two PRs
    otherwise).
  • This PR's title starts with name of package that is most changed in the PR, ex.
    services/friendbot, or all or doc if the changes are broad or impact many
    packages.

Thoroughness

  • This PR adds tests for the most critical parts of the new functionality or fixes.
  • I've updated any docs (developer docs, .md
    files, etc... affected by this change). Take a look in the docs folder for a given service,
    like this one.

Release planning

  • I've updated the relevant CHANGELOG (here for Horizon) if
    needed with deprecations, added features, breaking changes, and DB schema changes.
  • I've decided if this PR requires a new major/minor version according to
    semver, or if it's mainly a patch change. The PR is targeted at the next
    release branch if it's not a patch change.

What

Add option to submit without waiting for transaction final state. Transactions submitted with the additional parameter async=true are submitted directly to the submitter (stellar-core) and a pending transaction response is returned with a HTTP status code 202 Accepted.

Why

Applications do not always want to keep a http connection open for ~5 seconds to find out the final state of the submitted transaction. In some cases applications would prefer to submit and lookup the transaction later to see if it was successful, failed, or just not included.

Technically if an application was to cover all edge cases it would need to support that later lookup anyway, because it is possible for the Horizon to timeout, or the connection to be interrupted. It's also always possible for a submitted transaction to be scooped up by some other party if the transaction has been broadcasted or shared, and for that other party to resubmit the transaction during its time bound window of validity, even if Horizon fails the transaction immediately on the initial submit.

For applications that implement these edge cases already, submitting without waiting may be attractive.

Known limitations

This PR includes no tests for the new behavior of the endpoint. I've been working on a test, but it's a work-in-progress, and I'm learning a bit about how action tests work so it's taking me a bit longer.

@leighmcculloch leighmcculloch changed the base branch from master to release-horizon-v2.2.1 April 27, 2021 16:24
@leighmcculloch
Copy link
Member Author

leighmcculloch commented Apr 27, 2021

@bartekn I'd like to propose this change as an experimental feature of Horizon that is only enabled if explicitly indicated. Is there a common way to flag and enable/disable experimental features in Horizon? Or should I just add a new config option to the top-level CLI?

Copy link
Contributor

@Shaptic Shaptic left a comment

Choose a reason for hiding this comment

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

This seems like a very valuable addition to our txsub model! I know I wasn't requested for review on this, but I thought I'd drop some thoughts anyway, mostly to clarify my own understanding of intent here.


return asBool, nil
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, we already have ?include_failed=true/false; there must be code parsing that out somewhere 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

I could only find a GetString function. It's possible I missed it. Thanks for pointing it out. This could be replaced with any existing function if there is one.

Copy link
Contributor

@Shaptic Shaptic Jun 15, 2021

Choose a reason for hiding this comment

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

Ah, we use a library for this I guess (see helpers.go::getParams():403) which is catered towards HTTP-style URLs.

Comment on lines +165 to 169
result := handler.Submitter.Submitter.Submit(r.Context(), info.raw)
return handler.responseAsync(r, info, result)
}

submission := handler.Submitter.Submit(
Copy link
Contributor

Choose a reason for hiding this comment

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

From my understanding, handler.Submitter.Submit (i.e. System::Submit()) will do interaction with the database, checking if the tx exists already, etc. then block until the submission is processed from the queue, all without accessing the lower-level submitter (i.e. it uses System's own APIs). OTOH, handler.Submitter.Submitter.Submit is the raw way to interact with Core and that's what you're doing here.

(the above is just a summary of the PR, for myself as notes and to confirm my understanding)

A few questions:

  1. Are we concerned at all about the lack of extra checks (e.g. checkTxAlreadyExists or helpers with handling badSeq) or metrics for this that System provides, or is the intent to let API consumers be true "power users"? If the latter (which I like in principle quite a bit), I'd love a long-term goal where this is actually the recommended way to submit txs while the existing way is more of a ?babysit=true for people who don't want to think too hard about txsub. Either way, maybe we want another System that does an async version of everything for an "official" implementation.

  2. This PR doesn't introduce any DB changes, and I'm wondering if we would want that (e.g. something like a inprogress=true/false column in the history_transactions table). Probably not, but I ask because...

  3. It's unclear to me what the recommended way to check transaction status is with this endpoint. I assume it's "tx is pending until GET /transactions/<hash> doesn't 404". At that point, the successful field is sufficient for the trivial success/failure case, and grokking the result_xdr should give specifics. Is that a fair assumption?

@bartekn bartekn closed this Jun 14, 2021
@bartekn bartekn deleted the branch stellar:release-horizon-v2.2.1 June 14, 2021 21:17
@bartekn
Copy link
Contributor

bartekn commented Jun 14, 2021

GH autoclosed this because I removed an old release branch. Unfortunately I can't reopen. Can you reopen against master this time?

@leighmcculloch leighmcculloch deleted the async-submit branch June 22, 2021 15:57
@leighmcculloch
Copy link
Member Author

@bartekn GitHub does not allow me to reopen the PR, or change its base branch. I believe someone else may be taking on turning this feature request and spike into a full fledged feature. If that happens and they'd like to use this code, they can checkout the code from this PR.

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.

services/horizon: support async transaction submission
3 participants