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

Handle expired orders in the app #923

Merged
merged 8 commits into from
Jul 12, 2023
Merged

Conversation

klochowicz
Copy link
Contributor

@klochowicz klochowicz commented Jul 7, 2023

  • prune expired orders in the app when maker or coordinator is offline
  • add a test that ensures we detect lack of orders

TODO:

  • Disable open/close buttons when there's no 'best price' for a given direction
  • disable 'close position' button if there's no price in that direction

image

@klochowicz klochowicz self-assigned this Jul 7, 2023
@klochowicz klochowicz linked an issue Jul 7, 2023 that may be closed by this pull request
4 tasks
@klochowicz klochowicz marked this pull request as draft July 7, 2023 08:19
@klochowicz

This comment was marked as resolved.

@klochowicz klochowicz force-pushed the feat/notice-expired-orders-in-app branch 2 times, most recently from 51e54b0 to 710319e Compare July 10, 2023 03:51
@klochowicz klochowicz marked this pull request as ready for review July 10, 2023 03:51
@klochowicz
Copy link
Contributor Author

Two remarks:

  • killing a process and spawning it again from the integration test is not great, but does the job - potentially we could have an endpoint on maker and coordinator to "disable" them for test purposes without killing the processes. This would simplify the current workaround.
  • @da-kami suggested that it might be good to add an event to the orderbook stream that informs subscribers about the pruning. I was leaning towards this as well, so let me know whether it would be useful to add it now or not.

@klochowicz klochowicz force-pushed the feat/notice-expired-orders-in-app branch 3 times, most recently from 444eaa3 to 05189e5 Compare July 10, 2023 06:12
@klochowicz

This comment was marked as resolved.

@klochowicz klochowicz force-pushed the feat/notice-expired-orders-in-app branch from 05189e5 to c14c168 Compare July 11, 2023 01:45
Copy link
Contributor

@da-kami da-kami left a comment

Choose a reason for hiding this comment

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

Happy to see this merged, but I think just disabling the buttons might be quite confusing.
The user does not know why the buttons are disabled - we should add some form of indicator that shows the connection status to orderbook / coordinator that makes it obvious that the buttons are disabled because there is not connection.

Alternatively we could also display a toast for now so the user know why when the user enters the screen.

kill_process("maker").expect("to be able to kill maker process");
assert!(!is_maker_running(), "maker should be stopped by now");

let wait_time = std::time::Duration::from_secs(70);
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ Would it be possible to make the expiry time configurable so we can set it to e.g. 5 seconds instead so this test does not have to wait for 70 seconds? 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it would be nice indeed, I will create a ticket for this!

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm against having a test which runs for 70+ seconds :/

Copy link
Contributor Author

@klochowicz klochowicz Jul 12, 2023

Choose a reason for hiding this comment

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

Moved the test into a separate PR #937

I also realised that I don't need to wait for that long, because maker is likely to have already sent an order (and wait_until! covers the rest).

this of course in pessimistic scenario will still go for way too long, but having #935 would be a good remedy.

mobile/native/src/orderbook.rs Show resolved Hide resolved
PositionChangeNotifier positionChangeNotifier = PositionChangeNotifier(positionService);

// We have to have current price, otherwise we can't take order
positionChangeNotifier.price = Price(bid: 30000.0, ask: 30000.0);
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I think could potentially solve this cleaner by adding an explicit Extension to the PositionChangeNotifier in the tests that adds a setter so we can set the price; then we don't have to expose the private _price.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think this adds anything, a direct getter and setter == a public member....

mobile/lib/features/trade/position_list_item.dart Outdated Show resolved Hide resolved
mobile/lib/features/trade/position_list_item.dart Outdated Show resolved Hide resolved
@klochowicz
Copy link
Contributor Author

Happy to see this merged, but I think just disabling the buttons might be quite confusing. The user does not know why the buttons are disabled - we should add some form of indicator that shows the connection status to orderbook / coordinator that makes it obvious that the buttons are disabled because there is not connection.

Alternatively we could also display a toast for now so the user know why when the user enters the screen.

I agree with you that this would be ideal, there's a ticket scheduled to do this for the upcoming iteration #915.

I typically try to split the plumbing / backend support for a feature from the ideal UX, to avoid painful rebasing and to be able to concentrate on flutter in the follow-ups. YMMV though.


#[tokio::test]
#[ignore = "need to be run with 'just e2e' command"]
async fn no_orders_when_counterparty_is_offline() {
Copy link
Contributor

Choose a reason for hiding this comment

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

The test name says that you should not expect an order if the counterparty is offline. This makes sense of course, but I guess what you are testing here is that outdated orders (older than 1m) are not beeing forwarded anymore?

I don't think there is any use in testing if a terminated binary is not sending orders anymore.

If you want to test expired orders, you can do a simpler test:

  1. Only start the coordinator and the app
  2. Manually post a NewOrder to the coordinator using a reqwest client. Here you can set the expiry to in Xsec.
  3. Assert that no new order arrives past this few seconds.

But even that test might not be that useful...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to test that we detect lack of orders when the counterparty goes offline. As it turns out, we didn't. So I wrote the code that prunes outdated orders in the app so the feature would be working.

I like your idea with 'faking' maker; we could have created one with different expiry.
I don't think that the test would be simpler, because we would need to kill the maker anyway, and start using a "fake" one, but it certainly would be faster!

I don't mind stripping out the test if you see no value in it.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't mind stripping out the test if you see no value in it.

Please treat me as an equal engineer, not as a your superior :)

Thinking about this more, can we write unit tests for this at the places where it matters? e.g.

  • here we write a test that no expired order is being forwarded
  • in the frontend we check if the order is still up2date when reading it.

Copy link
Contributor Author

@klochowicz klochowicz Jul 12, 2023

Choose a reason for hiding this comment

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

Perhaps let's rephrase it:

I don't mind stripping out the test if you see no value in it.

What I meant was that I'm OK with stripping out the test if it causes contention for any of the reviewers, as it's not strictly necessary for addressing the issue.

I wrote the test because things were supposed to work, and didn't (normal part of engineering process). IMHO it would be great if we keep the test as it's proven to be useful.

I believe integration tests like this are needed; we need to know how we behave when the other party is not available and have that tested.

The criticism for waiting 70s is very much valid, and there's an open ticket that would address it - the maker doesn't have HTTP API to control orders for now, so it was not easy to address in this PR.

🤔Could I have started with an unit test instead? I don't think so - unit tests were there, it's just this case was missed during the implementation phase.

If you would like to add additional unit tests, or schedule them for the iteration, I think it's a good idea (the more unit tests the better!).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@bonomat I have extracted the test into a separate PR, so it's not blocking the functionality: #937

@holzeis
Copy link
Contributor

holzeis commented Jul 11, 2023

🤔 i am bit late to the party, but is it so bad that we let an order fail if there is no match?

@klochowicz
Copy link
Contributor Author

🤔 i am bit late to the party, but is it so bad that we let an order fail if there is no match?

I'm not sure what are you referring to. IMHO you should disable the buttons where there is no orders in the orderbook and you cannot do anything.
of course one could hide it in the hope that no-one notices, but that's not good UX.

Monitor prices and position close events.
These events can be later asserted on in tests.
Until now the expired orders were never pruned in case the other party did not
explicitly deleted it. This would have happened
The package version changed recently, and it's only apparent after one runs the
project.
If there's no bid/ask price, disable the buttons that would react to it.
@klochowicz klochowicz force-pushed the feat/notice-expired-orders-in-app branch from 1cc6c5d to f27f80d Compare July 12, 2023 04:36
@holzeis
Copy link
Contributor

holzeis commented Jul 12, 2023

🤔 i am bit late to the party, but is it so bad that we let an order fail if there is no match?

I'm not sure what are you referring to. IMHO you should disable the buttons where there is no orders in the orderbook and you cannot do anything.

of course one could hide it in the hope that no-one notices, but that's not good UX.

Well, I guess the issue is that we are using the order price in the first place. That made it look odd as there is no price.

But we could also simply use the actual price (e.g. from bitmex) as reference, hit order and if we can't find a match, we fail the order.

I tend to prefer not disabling the buttons, but no need to action it. We might want to revisit that another time. 🙂

@klochowicz
Copy link
Contributor Author

🤔 i am bit late to the party, but is it so bad that we let an order fail if there is no match?

I'm not sure what are you referring to. IMHO you should disable the buttons where there is no orders in the orderbook and you cannot do anything.
of course one could hide it in the hope that no-one notices, but that's not good UX.

Well, I guess the issue is that we are using the order price in the first place. That made it look odd as there is no price.

I don't see it as an issue. If there is no order that can be taken, why would not show this fact?

But we could also simply use the actual price (e.g. from bitmex) as reference, hit order and if we can't find a match, we fail the order.

I tend to prefer not disabling the buttons, but no need to action it. We might want to revisit that another time. 🙂

again, it's poor UX to not disable the buttons when we know for a fact that they cannot succeed.
I agree with @da-kami that just disabling the buttons is not enough, and we should be more clear why they are disabled, but this is just a start.

@holzeis
Copy link
Contributor

holzeis commented Jul 12, 2023

Again, I do not agree on the poor UX argument. But as mentioned we don't have to action it now.

@klochowicz
Copy link
Contributor Author

Again, I do not agree on the poor UX argument. But as mentioned we don't have to action it now.

Please state your reasons, as I would love to understand your POV.

There's very little more frustrating experiences on the web that needing to submit a form to check whether we can submit a form.
if I understood your proposal correctly - what you are proposing, is needing to submit an order to see whether we can submit an order.

@klochowicz klochowicz force-pushed the feat/notice-expired-orders-in-app branch from f27f80d to a2f71b2 Compare July 12, 2023 05:11
@klochowicz
Copy link
Contributor Author

I'm merging this, as the unsolved issues are captured in the follow-up PR #937 or the follow-up ticket scheduled for this iteration: #915

@klochowicz
Copy link
Contributor Author

bors r+

@bors
Copy link
Contributor

bors bot commented Jul 12, 2023

Build succeeded!

The publicly hosted instance of bors-ng is deprecated and will go away soon.

If you want to self-host your own instance, instructions are here.
For more help, visit the forum.

If you want to switch to GitHub's built-in merge queue, visit their help page.

@bors bors bot merged commit 71c8237 into main Jul 12, 2023
7 checks passed
@bors bors bot deleted the feat/notice-expired-orders-in-app branch July 12, 2023 05:35
@holzeis
Copy link
Contributor

holzeis commented Jul 12, 2023

Again, I do not agree on the poor UX argument. But as mentioned we don't have to action it now.

Please state your reasons, as I would love to understand your POV.

There's very little more frustrating experiences on the web that needing to submit a form to check whether we can submit a form.

if I understood your proposal correctly - what you are proposing, is needing to submit an order to see whether we can submit an order.

  • Disabling the button presumes that we either have an immediate match or fail.
  • Enabled buttons will not guarantee that the order will not fail.
  • The order matching is the responsibility of the coordinator.

Bottom line, by disabling the buttons we already imply that there is no match. This might be the case now as we have a very simplified matching logic, but this will change.

In other words, I think it's perfectly fine to fail an order if there is no match. The App should not implement business logic which is in the responsibility of the coordinator.

@holzeis
Copy link
Contributor

holzeis commented Jul 12, 2023

Additionally, we will not learn about an trading attempt, indicating more demand.

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.

Deal with order unavailability in the 10101 app
4 participants