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

Start pricenode providers asynchronously #4890

Merged
merged 2 commits into from Feb 24, 2021

Conversation

jmacxx
Copy link
Contributor

@jmacxx jmacxx commented Dec 3, 2020

Fixes #4441

This guarantees that the pricenode will run even when there is a problem with a provider at startup. It simply calls the initial refresh() asynchronously rather than blocking the bean startup routine. To my point of view there is no difference between the first and subsequent calls to refresh, since providers can fail at any time. When rates are requested any non-initialized provider is ignored.

However I have not taken ownership of the pricenode and only have a superficial understanding of how the data is calculated. I did enough testing to check that the price and fee data looks good, and that the automated tests pass. There could certainly be edge cases that I'm not aware of. @cd2357 is certainly free to flame me if this is a stupid change, as he put a lot more work into it than I did.

@wiz
Copy link
Member

wiz commented Dec 4, 2020

Thanks for working on this. I think the main concern is what price do you return if there is no data for a given asset? In that case I assume you don't return anything, or a null value, right?

@jmacxx
Copy link
Contributor Author

jmacxx commented Dec 4, 2020

If there is no data for a given asset, that asset would not be present in the JSON data.

For example, running with only two providers: Kraken and Luno, the rate for ZAR is not present in the JSON data. ZAR is provided by Luno (not Kraken), but Luno service is down. If the Binance provider is included, the ZAR rate is present.

@ripcurlx ripcurlx requested a review from cd2357 December 4, 2020 15:55
@ripcurlx
Copy link
Member

ripcurlx commented Dec 4, 2020

@cd2357 Could you please give this code changes a quick ACK?

@cd2357
Copy link
Contributor

cd2357 commented Dec 4, 2020

My main concern is this:

  • let's say a pricenode cannot connect to one or more exchanges, but still starts up
    • this means that, worst case, it won't provide a price feed for some "unlucky" currencies / assets, which were only available on the currently-not-reachable exchanges
  • a Bisq node connects to this pricenode for price data
  • if this node wants to start a trade (or has any ongoing trade) in any of the above "unlucky" currencies, this could result in failed trades, or the inability to create/accept new trades. Also, not sure what other side-effects this would have for clients in general (NPEs, errors in UI or trade protocol, etc).

This is now avoided by the simple fact that a pricenode always provides a price for all known / expected currencies :

  • If an exchange is not reachable during pricenode startup, then the startup fails until that exchange is reachable again (not ideal, I know, but at least protects Bisq nodes from the scenario above).
  • If a pricenode starts with all exchanges reachable, but some exchange becomes unreachable later on, the scenario above is still not an issue, because that pricenode will serve the "cached" (or last known) price for the affected currencies or assets -- until the problematic exchange comes back online again. Actually, I think the pricenode will provide an aggregated price for the affected currencies (if the aggregate price is an average of 3 prices from 3 exchanges, and one exchange goes offline, then the pricenode will serve an aggregate price based on the current data from the 2 working exchanges + the "cached" latest known price from the 3rd exchange, until that exchange comes back online).

I admit this is mainly a theoretical concern (I didn't test it out and see errors), but it seems reasonable that these risks are possible. Most "at risk" currencies are those with a small number of "inputs" in the aggregate price, like those depending on 1-2-3 exchanges: https://bisq.wiki/Bisq_Price_Indices . For example, lots of fiat currencies have only 1 provider (BitPay).

How do you see this?

Is this an acceptable risk, or maybe am I over-estimating it?

If not, how could it be mitigated? One possible solution that comes to mind is that pricenodes periodically persist to disk the latest-known prices for all supported currencies, then if they are restarted and some exchanges are temporarily unreachable, they could report the "cached" price for those currencies until the faulty exchanges come back online. (This cache approach is already in place, but the prices are cached in-memory, not persisted on-disk.)

cc @bisq-network/pricenode-operators

@jmacxx
Copy link
Contributor Author

jmacxx commented Dec 5, 2020

Good points. When rates are not available Bisq displays the price as of the last trade:
image

If you try and take an offer this message prevents it:
image

Likewise making an offer it forces you to enter a fixed price:
image

Or of you had an already published market rate offer; your price feed is down and someone tries to take it they get this:
image

@cd2357
Copy link
Contributor

cd2357 commented Dec 5, 2020

What happens if

  • user creates market rate offer (when pricefeed for that currency is available)
  • user disables offer
  • pricefeed for that currency becomes unavailable (user restarts Bisq, chooses a pricenode without that feed)
  • user re-enables offer

Does re-enabling the offer fail graciously?

Also, if shortly after that the pricefeed becomes available again (Bisq client didn't restart, kept using same pricenode, but not pricenode starts providing the needed pricefeed) -- will the client detect that and allow the user to re-enable the offer / create new offers in that currency?

@jmacxx
Copy link
Contributor Author

jmacxx commented Dec 6, 2020

Per your first question, re-enabling the offer does not fail, you can disable/enable at will. The status of the pricefeed is not taken into account. The trading protocol would prevent a market based offer from being taken due to the price feed being N/A.

Per your second question, offers can still be created when the pricefeed is down. If the pricefeed fails while Bisq is running, the user can still create market based offers. If Bisq starts up with no pricefeed available the user is only allowed to create fixed price offers.

@cd2357
Copy link
Contributor

cd2357 commented Dec 7, 2020

In that case, it sounds good from my side. Thanks for the detailed answers @jmacxx.

@wiz do you want to coordinate more extensive tests on this first? Or is this fine and can be merged?

@cd2357 cd2357 self-requested a review December 7, 2020 22:44
@ripcurlx
Copy link
Member

As pricenode providers are running from specific master versions anyways I'm not merging this for v1.5.2. Waiting for testing by @wiz.

@ripcurlx
Copy link
Member

@wiz ☝️

@jmacxx
Copy link
Contributor Author

jmacxx commented Feb 12, 2021

@wiz did this get installed to production? It seemed like a high priority when you were complaining about it asking for it to be fixed.

@wiz
Copy link
Member

wiz commented Feb 18, 2021

@jmacxx sorry for the late reply, yes it was a high priority because it can cause pricenodes to completely fail to startup. I apologize I haven't had time to properly ACK the PR but IIRC it's running on my pricenode server for a while now. @Emzy would you mind testing/reviewing this PR ?

@Emzy
Copy link
Contributor

Emzy commented Feb 18, 2021

I have this PR as a test running on my pricenode "emzypricpidesmyqg2hc6dkwitqzaxrqnpkdg3ae2wef5znncu2ambqd.onion"

@ripcurlx
Copy link
Member

@Emzy @wiz As soon as I have an ACK from either of you I'll move forward and merge this PR.

@Emzy
Copy link
Contributor

Emzy commented Feb 23, 2021

ACK
No issues on my production pricenode.

Copy link
Member

@ripcurlx ripcurlx left a comment

Choose a reason for hiding this comment

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

utACK - based on #4890 (comment)

@ripcurlx ripcurlx merged commit dc38117 into bisq-network:master Feb 24, 2021
@ripcurlx ripcurlx added this to the v1.5.7 milestone Feb 24, 2021
@jmacxx jmacxx deleted the fix_pricenode branch May 29, 2022 22:48
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.

Bisq Pricenode crashes on startup if any providers are unavailable for first query
5 participants