Open 0xmovses opened 2 weeks ago
First, I'll explain how I understand this code to ensure we're aligned on what needs to be done.
The function poll_next_event
in the BlockchainService
trait is integrated into a stream of ContractEvent
events. Each time the poll_next
function is called, it invokes the two poll methods from CounterpartyContractMonitoring
and InitiatorContractMonitoring
. This implementation returns when either of the two methods returns. The possible cases are:
Poll::Ready(Some(first event))
. The stream returns Some(first event),
and the function is called again to get the next event.
Poll::Ready(Some(second event))
.self.counterparty_monitoring().poll_next_unpin(cx)
is discarded.The proposed solutions don’t address this issue. I don’t fully understand the second solution, but like the first, it only returns one event.
I don't see the issue with returning Poll::Pending
. In the test test_bridge_poll_stuck()
, we initialize both sources with events. There's no reason to receive a Poll::Pending if the polling method works correctly. If Poll::Pending is returned, it suggests that the polling method of one or both services isn't working as expected because they aren’t returning their events. The test also doesn't verify that all events from both sources are received. Since both sources contain events, we should get all of them. Because the code doesn't handle the (Ready, Ready) case, there's a strong chance that it will fail.
Yes, you're right.
We should handle the (Ready, Ready) case though as that will be a likely case.
To do that, there are 2 possibilities, I think:
Option<ContractEvent<_>>
. In fact, we return the result of the execution of the 2 methods. It changes the BlockchainService
signature and how the event is processed.I don't have a real opinion. It seems the second do fewer changes, but I'm not sure as I don't know all the code that process event. Tell which you prefer.
Second choice 🙏
Summary
The blockchain service could be stuck in Pending due to how the initiator and counterparty events are processes simultaneously: If both events are polled at the same time, Pending is returned (source)
Add this PoC in protocol-units/bridge/shared/tests/blockchain_service.rs
Possible Solutions
Event Queuing
Idea: Queue up the events from the initiator and counterparty separately. When an event is detected, enqueue it and process the queue in order, ensuring that events are processed one at a time. Implementation: Maintain separate queues for initiator and counterparty events, and process each queue in the order events were received.
Atomic State Management
Idea: Use atomic state management to keep track of the state of event processing. For example, you can use an atomic flag to ensure that only one event (from either the initiator or counterparty) is processed at any given time. Implementation: An atomic flag can be used to track whether the system is currently processing an event. If one event is being processed, other events are temporarily ignored until the first one is completed.