hermes_relayer_components/relay/impls/packet_relayers/general/
lock.rs

1use core::marker::PhantomData;
2
3use hermes_logging_components::traits::has_logger::HasLogger;
4use hermes_logging_components::traits::logger::CanLog;
5
6use crate::relay::traits::chains::HasRelayChains;
7use crate::relay::traits::packet_lock::HasPacketLock;
8use crate::relay::traits::packet_relayer::PacketRelayer;
9
10/**
11   Call the inner relayer only if the packet lock provided by [`HasPacketLock`]
12   is acquired.
13
14   This is to avoid race condition where multiple packet relayers try to
15   relay the same packet at the same time.
16*/
17pub struct LockPacketRelayer<InRelayer>(pub PhantomData<InRelayer>);
18
19pub struct LogSkipRelayLockedPacket<'a, Relay>
20where
21    Relay: HasRelayChains,
22{
23    pub relay: &'a Relay,
24    pub packet: &'a Relay::Packet,
25}
26
27impl<Relay, InRelayer> PacketRelayer<Relay> for LockPacketRelayer<InRelayer>
28where
29    Relay: HasRelayChains + HasPacketLock + HasLogger,
30    InRelayer: PacketRelayer<Relay>,
31    Relay::Logger: for<'a> CanLog<LogSkipRelayLockedPacket<'a, Relay>>,
32{
33    async fn relay_packet(relay: &Relay, packet: &Relay::Packet) -> Result<(), Relay::Error> {
34        let m_lock = relay.try_acquire_packet_lock(packet).await;
35
36        match m_lock {
37            Some(_lock) => InRelayer::relay_packet(relay, packet).await,
38            None => {
39                relay.logger().log(
40                    "skip relaying packet, as another packet relayer has acquired the packet lock",
41                    &LogSkipRelayLockedPacket {
42                        relay,
43                        packet,
44                    }).await;
45
46                Ok(())
47            }
48        }
49    }
50}