Open abitmore opened 6 years ago
Note that this problem also occurs with fill orders. If an order fills instantly on creation then the market subscription
callback is sometimes called first and then the transaction is processed. The order of the callbacks in this case seems to be indeterministic, unlike the bug mentioned above which seems to be deterministic from my tests.
I think we can defer the fill_order
notification until notifications about changed object are sent, e.g. temporarily save it somewhere, then send it after sent other notifications.
Actually I misread the issue above. The problem you described is concerning the fill orders. The original problem we discussed in earlier chats was about the order creation notification (ie subscribe_to_market
firing before the response of broadcast_transaction_synchronous
is sent back to the client.
For example, the output of:
"{ 'id': -1, 'method': 'call', 'params': [2, subscribe_to_market, [9001, "1.3.0", "1.3.21"]] }"
is being returned to the client before the output of:
"{ 'id': 1, 'method': 'call', 'params': [network_broadcast, broadcast_transaction_synchronous,[%s]]}"
One would expect that the transaction would be confirmed first before it is broadcasted as an event. I think this is a minor issue though, the fill order bug is certainly more problematic
I think that if we consider the above bug^^ I mentioned to be not a problem, then its fine to leave the fill order bug as it currently is because the client can just listen for fill orders that do not have a matching order and put them in an "orphan" list, then when the order arrives the client can fill the order. It's a bit troublesome but I think if implemented well the code can run without any issues.
What are your thoughts @abitmore @pmconrad @elmato ?
@arminnaderi actually I misunderstood your question earlier. Please create a new issue for that.
Ok, will do now
Your issue is still related though. Notification of broadcast_transaction_synchronous
is fired by applied_block
signal (which is same to order fills but of different API container), notification of new orders is fired by changed_objects
signal, there are threading involved so the order is not deterministic. In addition, because they're not in the same container (one is in network_broadcast_api
and the other is in database_api
), I think it's harder to fix.
Yeah, maybe we can continue the discussion in this issue, the two issues are very related IMO. I don't have a problem with this not being fixed because there is a workaround I can code on the client side, but I just want to confirm that the two mentioned problems aren't considered bugs and they won't be "fixed" in the future, because if I do code the workarounds and these methods gets patched it will be a waste of effort. Better to fix it now if it will be fixed in the future anyway
Do you think the threads will be synchronized in the future, or if this problem is considered a "bug"?
Don't think this issue can be fixed in a manner that doesn't cause side effect problems, requesting close
It's still somewhat a bug. Although we're unable to fix it now, but perhaps can fix it in the future. So I'll keep this issue open.
What I meant is order fill events and order creation events are not the only two events that are pushed by on_applied_block()
and on_objects_changed()
. Some clients might actually have no preference in the order of these events. However, I agree that order fill events should probably come after order creation events, if its fixed it will affect all other events that are pushed by these methods as a side effect
Assigned to @OpenLedgerApp
I initialized some work in this issue however i didn't assigned myself and i didn't made a lot yet. Will like to know where @openledgerapp is up as i maybe can keep it or if they are advanced i can just abandon it.
We have already spent our hours on this issue. So, we want to keep it on us
ok, no worries.
Thanks!
Sorry, @oxarbitrage I did not realize you already had some effort into this one. If you have anything to PR that may assist @OpenLedgerApp in their development, please do so. Thanks
Currently, from one side: Database_api subscribes to the events from DB (new, changed, removed) object. Filters and accumulates events related to (call_order_object, limit_order_object, force_settlement_object) and finally via fc::async notifies listeners.
From other side: Database_api subscribes to the event from DB (applied_block), Filters operations and accumulates events related to (fill_order_operation) and via fc::async notifies listeners.
There are some inconveniences: 1: Full match in the same block - Database_api emits only two fill_order events 2: Order of events from Database_api is not well defined as Database_api in fc::async use different queue for listeners. 3: Listeners receive different objects: *_order_oject, {fill_order_operation, fill_order_operation_result} or object_id
This is draft version: and could be extended. We propose to extend Database_api: Use only applied_block for filtering operations and accumulates events related to (limit_order_create_operation, fill_order_operation, limit_order_cancel_operation) and notifies listeners. In this approach listeners will receive notifications regardless where they were happened (in the same block or not) and order will be defined. See https://github.com/openledger/bitshares-core/commit/677a1517d2fb3f5be372f077ead80ce82ac7ad55
I'm the original person who brought this issue up. It's not a problem anymore as it can be fixed client-side.
Websocket events are asynchronous and not guaranteed to come in any particular order.
@OpenLedgerApp Could you clarify what you mean by 1), "Full match in the same block" ? (With an example please)
create_sell_order(alice, core.amount(100), usd.amount(100)); create_sell_order(bob, usd.amount(100), core.amount(100)); If these operations are matched in the same block, listener will get only two fill_order notifications. @arminnaderi Could you share a bit more context where you faced with this problem (#1277)?
@OpenLedgerApp You mean the listener will only send 2 fill_order notifications, and 0 order_creation (transaction callbacks) ?
I faced this problem when creating an order which was instantly filled in the same block. But the problem can be fixed client-side, it's not actually a technical bug.
Please check if you are receiving the transaction callbacks and paste your findings here - You need to set an id when sending broadcast_transaction_synchronous and check if you receive a response with a matching id
You mean the listener will only send 2 fill_order notifications, and 0 order_creation (transaction callbacks) ?
Yes, database_api raises 2 fill_order notifications, and 0 order_creation.
I wonder if it is important for listener to receive notifications {order_creation, fill_order, cancel_order}? If Yes, it https://github.com/bitshares/bitshares-core/issues/1277#issuecomment-467416486 could help, Otherwise it is not done in current implementation. Use case: It is the case if orders are particularly matched in the different blocks: steps: 1: create_sell_order(alice, core.amount(100), usd.amount(100)); 2: wait some blocks 3: create_sell_order(bob, usd.amount(200), core.amount(200)); result: we have the following order of events: order_creation -> fill_order->fill_odrer -> order_creation as it is mentioned #1277.
It is correct behavior! In the 1st step order is created and not matched. Then in the 3d step partly matching is happened (fill_order, fill_order ) and finally a new order was created (order_creation).
If the order was fully filled the moment it was created, no order_creation will be notified. This is normal behavior. Instead, a full_order_object will be sent to the websocket listener, which is basically a copy of the order
If the order was fully filled the moment it was created, no order_creation will be notified. This is normal behavior. Instead, a full_order_object will be sent to the websocket listener, which is basically a copy of the order
Yes, the same logic I've mentioned above. Are there any more requirements to #1277?
Nope, that's why I mentioned there is no bug. You have all the information you need to properly handle the relevant events.
Also, @OpenLedgerApp , please vote against the "Reduce MSSR of bitCNY to 1.02" poll worker if you want bitCNY to not go into global settlement. If a global settlement on an asset as crucial as bitCNY happens, many users will leave and it will hurt your bottom line.
No politics here please.
@OpenLedgerApp expected behavior is described in OP:
when a new order is placed, clients receive an order creation event first, then an order fill event.
Take your use case as an example:
Use case: It is the case if orders are particularly matched in the different blocks: steps: 1: create_sell_order(alice, core.amount(100), usd.amount(100)); 2: wait some blocks 3: create_sell_order(bob, usd.amount(200), core.amount(200)); result: we have the following order of events: order_creation -> fill_order->fill_odrer -> order_creation as it is mentioned #1277.
It is correct behavior! In the 1st step order is created and not matched. Then in the 3d step partly matching is happened (fill_order, fill_order ) and finally a new order was created (order_creation).
IMHO the correct order of events should be: order_creation(alice), order_creation(bob), fill_order(alice), fill_order(bob), no matter if alice's order or bob's has been fully filled or both.
@OpenLedgerApp expected behavior is described in OP:
when a new order is placed, clients receive an order creation event first, then an order fill event.
Take your use case as an example:
Use case: It is the case if orders are particularly matched in the different blocks: steps: 1: create_sell_order(alice, core.amount(100), usd.amount(100)); 2: wait some blocks 3: create_sell_order(bob, usd.amount(200), core.amount(200)); result: we have the following order of events: order_creation -> fill_order->fill_odrer -> order_creation as it is mentioned #1277. It is correct behavior! In the 1st step order is created and not matched. Then in the 3d step partly matching is happened (fill_order, fill_order ) and finally a new order was created (order_creation).
IMHO the correct order of events should be: order_creation(alice), order_creation(bob), fill_order(alice), fill_order(bob), no matter if alice's order or bob's has been fully filled or both.
@abitmore it could be done via operations. see https://github.com/openledger/bitshares-core/commit/677a1517d2fb3f5be372f077ead80ce82ac7ad55. You are welcome to discuss it. Thanks.
We have two issues here:
The ~second~first point is a bug IMO, while the ~first~second may simply be unexpected but valid behaviour (if message order is not guaranteed like @arminnaderi said).
@pmconrad I think the first issue is a bug from the perspective of writing clients, because you don't actually know if your order was created or not. Assuming that an order was created because a fill event pops up is too complicated.
Also, as I mentioned a few posts above, when the order is fully filled on creation, a full_order_object is sent to the websocket listener instead of the callback to broadcast_transaction - I agree it's a bit complicated to check for the full_order_object though
We have made PR - https://github.com/bitshares/bitshares-core/pull/1636
This PR describes a draft vision of market events model.
I have built some unit tests for creating markets and trades.
A simple bandaid for this that might make life easier for the developers of client apps would be to include more order fields in the fill notification, notably the "for_sale" quantity, such that it could be used to initialize an object locally and to verify ordering of events.
I have built some unit tests for creating markets and trades. This may help test this issue. I will update this comment when I find the relevant code.
When you can provide this test?
Sorry. I found it and then got distracted. Here it is:
https://github.com/bitshares/bitshares-core/pull/1661
Oh look! A squirrel....
Sorry. I found it and then got distracted. Here it is:
1661
Oh look! A squirrel....
Thanks. Sure, this may help test this issue, but the use case, mentioned above, that reproduces the #1277 is not so complicated.
Bug Description
A client that subscribed to a market always receives order fill events before order creation events if the orders are partially filled in a same block. Note: no notification on order creation if it gets completely filled in same block (not sure if it need to be fixed so far).
There is a
FIXME
in code: https://github.com/bitshares/bitshares-core/blob/d94cc574b2ca460dd636e573f25f0c7737b4a355/libraries/app/database_api.cpp#L2311-L2313Probably because
on_applied_block()
is called beforeon_objects_changed()
: https://github.com/bitshares/bitshares-core/blob/d94cc574b2ca460dd636e573f25f0c7737b4a355/libraries/chain/db_block.cpp#L540-L544Expected Behavior When a new order is placed, clients receive an order creation event first, then an order fill event.
Additional Context (optional) I'm not sure if it's safe to simply move
on_objects_changed()
to be called beforeon_applied_block()
.Impacts Describe which portion(s) of BitShares Core may be impacted by this bug. Please tick at least one box.
CORE TEAM TASK LIST