use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
use std::sync::Arc;

/// Chains supported by reth. First value should be used as the default.
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];

/// Clap value parser for [`ChainSpec`]s.
///
/// The value parser matches either a known chain, the path
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
    Ok(match s {
        "mainnet" => MAINNET.clone(),
        "sepolia" => SEPOLIA.clone(),
        "holesky" => HOLESKY.clone(),
        "hoodi" => HOODI.clone(),
        "dev" => DEV.clone(),
        _ => Arc::new(parse_genesis(s)?.into()),
    })
}

/// Ethereum chain specification parser.
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct EthereumChainSpecParser;

impl ChainSpecParser for EthereumChainSpecParser {
    type ChainSpec = ChainSpec;

    const SUPPORTED_CHAINS: &'static [&'static str] = SUPPORTED_CHAINS;

    fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
        chain_value_parser(s)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use reth_chainspec::EthereumHardforks;

    #[test]
    fn parse_known_chain_spec() {
        for &chain in EthereumChainSpecParser::SUPPORTED_CHAINS {
            assert!(<EthereumChainSpecParser as ChainSpecParser>::parse(chain).is_ok());
        }
    }

    #[test]
    fn parse_raw_chainspec_hardforks() {
        let s = r#"{
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "stateRoot": "0x76f118cb05a8bc558388df9e3b4ad66ae1f17ef656e5308cb8f600717251b509",
  "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  "bloom": "0x000...000",
  "difficulty": "0x00",
  "number": "0x00",
  "gasLimit": "0x016345785d8a0000",
  "gasUsed": "0x00",
  "timestamp": "0x01",
  "extraData": "0x00",
  "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x0000000000000000",
  "baseFeePerGas": "0x07",
  "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  "blobGasUsed": "0x00",
  "excessBlobGas": "0x00",
  "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "requestsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  "hash": "0xc20e1a771553139cdc77e6c3d5f64a7165d972d327eee9632c9c7d0fe839ded4",
  "alloc": {},
  "config": {
    "ethash": {},
    "chainId": 1,
    "homesteadBlock": 0,
    "daoForkSupport": true,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "berlinBlock": 0,
    "londonBlock": 0,
    "terminalTotalDifficulty": 0,
    "shanghaiTime": 0,
    "cancunTime": 0,
    "pragueTime": 0,
    "osakaTime": 0
  }
}"#;

        let spec = <EthereumChainSpecParser as ChainSpecParser>::parse(s).unwrap();
        assert!(spec.is_shanghai_active_at_timestamp(0));
        assert!(spec.is_cancun_active_at_timestamp(0));
        assert!(spec.is_prague_active_at_timestamp(0));
        assert!(spec.is_osaka_active_at_timestamp(0));
    }
}


use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
use std::sync::Arc;

/// Chains supported by reth. First value should be used as the default.
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];

/// Clap value parser for [`ChainSpec`]s.
///
/// The value parser matches either a known chain, the path
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.

pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
    Ok(match s {
        "mainnet" => MAINNET.clone(),
        "sepolia" => SEPOLIA.clone(),
        "holesky" => HOLESKY.clone(),
        "hoodi" => HOODI.clone(),
        "dev" => DEV.clone(),
        _ => Arc::new(parse_genesis(s)?.into()),
    })
}

/// Ethereum chain specification parser.
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct EthereumChainSpecParser;

impl ChainSpecParser for EthereumChainSpecParser {
    type ChainSpec = ChainSpec;

    const SUPPORTED_CHAINS: &'static [&'static str] = SUPPORTED_CHAINS;

    fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
        chain_value_parser(s)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use reth_chainspec::EthereumHardforks;

    #[test]
    fn parse_known_chain_spec() {
        for &chain in EthereumChainSpecParser::SUPPORTED_CHAINS {
            assert!(<EthereumChainSpecParser as ChainSpecParser>::parse(chain).is_ok());
        }
    }

    #[test]
    fn parse_raw_chainspec_hardforks() {
        let s = r#"{
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "stateRoot": "0x76f118cb05a8bc558388df9e3b4ad66ae1f17ef656e5308cb8f600717251b509",
  "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  "bloom": "0x000...000",
  "difficulty": "0x00",
  "number": "0x00",
  "gasLimit": "0x016345785d8a0000",
  "gasUsed": "0x00",
  "timestamp": "0x01",
  "extraData": "0x00",
  "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "nonce": "0x0000000000000000",
  "baseFeePerGas": "0x07",
  "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  "blobGasUsed": "0x00",
  "excessBlobGas": "0x00",
  "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "requestsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  "hash": "0xc20e1a771553139cdc77e6c3d5f64a7165d972d327eee9632c9c7d0fe839ded4",
  "alloc": {},
  "config": {
    "ethash": {},
    "chainId": 1,
    "homesteadBlock": 0,
    "daoForkSupport": true,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "berlinBlock": 0,
    "londonBlock": 0,
    "terminalTotalDifficulty": 0,
    "shanghaiTime": 0,
    "cancunTime": 0,
    "pragueTime": 0,
    "osakaTime": 0
  }
}"#;

        let spec = <EthereumChainSpecParser as ChainSpecParser>::parse(s).unwrap();
        assert!(spec.is_shanghai_active_at_timestamp(0));
        assert!(spec.is_cancun_active_at_timestamp(0));
        assert!(spec.is_prague_active_at_timestamp(0));
        assert!(spec.is_osaka_active_at_timestamp(0));
    }
}


use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
use std::sync::Arc;

/// Chains supported by reth. First value should be used as the default.
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];

/// Clap value parser for [`ChainSpec`]s.
///
/// The value parser matches either a known chain, the path
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error>

{
    Ok(match s {
        "mainnet" => MAINNET.clone(),
        "sepolia" => SEPOLIA.clone(),
        "holesky" => HOLESKY.clone(),
        "hoodi" => HOODI.clone(),
        "dev" => DEV.clone(),
        _ => Arc::new(parse_genesis(s)?.into()),
    })
}


use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
use std::sync::Arc;

/// Chains supported by reth. First value should be used as the default.
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];

/// Clap value parser for [`ChainSpec`]s.
///
/// The value parser matches either a known chain, the path
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
    Ok(match s {
        "mainnet" => MAINNET.clone(),
        "sepolia" => SEPOLIA.clone(),
        "holesky" => HOLESKY.clone(),
        "hoodi" => HOODI.clone(),
        "dev" => DEV.clone(),
        _ => Arc::new(parse_genesis(s)?.into()),
    })
}

/// Ethereum chain specification parser.
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct EthereumChainSpecParser;

impl ChainSpecParser for EthereumChainSpecParser {
    type ChainSpec = ChainSpec;

    const SUPPORTED_CHAINS: &'static [&'static str] = SUPPORTED_CHAINS;

    fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
        chain_value_parser(s)
    }
}


use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
use std::sync::Arc;

/// Chains supported by reth. First value should be used as the default.
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];

/// Clap value parser for [`ChainSpec`]s.
///
/// The value parser matches either a known chain, the path
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
    Ok(match s {
        "mainnet" => MAINNET.clone(),
        "sepolia" => SEPOLIA.clone(),
        "holesky" => HOLESKY.clone(),
        "hoodi" => HOODI.clone(),
        "dev" => DEV.clone(),
        _ => Arc::new(parse_genesis(s)?.into()),
    })
}

/// Ethereum chain specification parser.
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct EthereumChainSpecParser;

impl ChainSpecParser for EthereumChainSpecParser {
    type ChainSpec = ChainSpec;

    const SUPPORTED_CHAINS: &'static [&'static str] = SUPPORTED_CHAINS;

    fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
        chain_value_parser(s)
    }


use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
use std::sync::Arc;

/// Chains supported by reth. First value should be used as the default.
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];

/// Clap value parser for [`ChainSpec`]s.
///
/// The value parser matches either a known chain, the path
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
    Ok(match s {
        "mainnet" => MAINNET.clone(),
        "sepolia" => SEPOLIA.clone(),
        "holesky" => HOLESKY.clone(),
        "hoodi" => HOODI.clone(),
        "dev" => DEV.clone(),
        _ => Arc::new(parse_genesis(s)?.into()),
    })
}

/// Ethereum chain specification parser.
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct EthereumChainSpecParser;

impl ChainSpecParser for EthereumChainSpecParser {
    type ChainSpec = ChainSpec;

    const SUPPORTED_CHAINS: &'static [&'static str] = SUPPORTED_CHAINS;

    fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>>


use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
use std::sync::Arc;

/// Chains supported by reth. First value should be used as the default.
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];

/// Clap value parser for [`ChainSpec`]s.
///
/// The value parser matches either a known chain, the path
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
    Ok(match s {
        "mainnet" => MAINNET.clone(),
        "sepolia" => SEPOLIA.clone(),
        "holesky" => HOLESKY.clone(),
        "hoodi" => HOODI.clone(),
        "dev" => DEV.clone(),
        _ => Arc::new(parse_genesis(s)?.into()),
    })
}

/// Ethereum chain specification parser.
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct EthereumChainSpecParser;

impl ChainSpecParser for EthereumChainSpecParser {
    type ChainSpec = ChainSpec;

    const SUPPORTED_CHAINS: &'static [&'static str] = SUPPORTED_CHAINS;

    fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
        chain_value_parser(s)
    }
}

#[cfg(test)]
mod tests {


use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
use std::sync::Arc;

/// Chains supported by reth. First value should be used as the default.
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];

/// Clap value parser for [`ChainSpec`]s.
///
/// The value parser matches either a known chain, the path
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
    Ok(match s {
        "mainnet" => MAINNET.clone(),
        "sepolia" => SEPOLIA.clone(),
        "holesky" => HOLESKY.clone(),
        "hoodi" => HOODI.clone(),
        "dev" => DEV.clone(),
        _ => Arc::new(parse_genesis(s)?.into()),
    })
}

/// Ethereum chain specification parser.
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct EthereumChainSpecParser;

impl ChainSpecParser for EthereumChainSpecParser {
    type ChainSpec = ChainSpec;

    const SUPPORTED_CHAINS: &'static [&'static str] = SUPPORTED_CHAINS;

    fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
        chain_value_parser(s)
    }
}

#[cfg(test)]
mod tests {
    use super::*;


use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
use std::sync::Arc;

/// Chains supported by reth. First value should be used as the default.
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];

/// Clap value parser for [`ChainSpec`]s.
///
/// The value parser matches either a known chain, the path
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
    Ok(match s {
        "mainnet" => MAINNET.clone(),
        "sepolia" => SEPOLIA.clone(),
        "holesky" => HOLESKY.clone(),
        "hoodi" => HOODI.clone(),
        "dev" => DEV.clone(),
        _ => Arc::new(parse_genesis(s)?.into()),
    })
}

/// Ethereum chain specification parser.
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct EthereumChainSpecParser;

impl ChainSpecParser for EthereumChainSpecParser {
    type ChainSpec = ChainSpec;

    const SUPPORTED_CHAINS: &'static [&'static str] = SUPPORTED_CHAINS;

    fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
        chain_value_parser(s)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use reth_chainspec::EthereumHardforks;

    #[test]

    fn parse_known_chain_spec() {
        for &chain in EthereumChainSpecParser::SUPPORTED_CHAINS {
            assert!(<EthereumChainSpecParser as ChainSpecParser>::parse(chain).is_ok());
        }
    }


use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
use std::sync::Arc;

/// Chains supported by reth. First value should be used as the default.
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];

/// Clap value parser for [`ChainSpec`]s.
///
/// The value parser matches either a known chain, the path
/// to a json file, or a json formatted string in-memory. The json needs to be a Genesis struct.
pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
    Ok(match s {
        "mainnet" => MAINNET.clone(),
        "sepolia" => SEPOLIA.clone(),
        "holesky" => HOLESKY.clone(),
        "hoodi" => HOODI.clone(),
        "dev" => DEV.clone(),
        _ => Arc::new(parse_genesis(s)?.into()),
    })
}

/// Ethereum chain specification parser.
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub struct EthereumChainSpecParser;

impl ChainSpecParser for EthereumChainSpecParser {
    type ChainSpec = ChainSpec;

    const SUPPORTED_CHAINS: &'static [&'static str] = SUPPORTED_CHAINS;

    fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
        chain_value_parser(s)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use reth_chainspec::EthereumHardforks;

    #[test]
    fn parse_known_chain_spec()

{
        for &chain in EthereumChainSpecParser::SUPPORTED_CHAINS {
            assert!(<EthereumChainSpecParser as ChainSpecParser>::parse(chain).is_ok());
        }
    }


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use futures::Stream;
use metrics::Counter;
use reth_primitives_traits::InMemorySize;
use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};
use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};
use tokio_util::sync::{PollSendError, PollSender};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.
pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.
pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>) {
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> MeteredSender<T> {
    /// Creates a new [`MeteredSender`] wrapping around the provided [Sender](mpsc::Sender)
    pub fn new(sender: mpsc::Sender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve_owned`.
    pub fn try_reserve_owned(self) -> Result<OwnedPermit<T>, TrySendError<Self>> {
        let Self { sender, metrics } = self;
        sender.try_reserve_owned().map(|permit| OwnedPermit::new(permit, metrics.clone())).map_err(
            |err| match err {
                TrySendError::Full(sender) => TrySendError::Full(Self { sender, metrics }),
                TrySendError::Closed(sender) => TrySendError::Closed(Self { sender, metrics }),
            },
        )
    }

    /// Waits to acquire a permit to send a message and return owned permit.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve_owned`.
    pub async fn reserve_owned(self) -> Result<OwnedPermit<T>, SendError<()>> {
        self.sender.reserve_owned().await.map(|permit| OwnedPermit::new(permit, self.metrics))
    }

    /// Waits to acquire a permit to send a message.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve`.
    pub async fn reserve(&self) -> Result<Permit<'_, T>, SendError<()>> {
        self.sender.reserve().await.map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve`.
    pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
        self.sender.try_reserve().map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Returns the underlying [Sender](mpsc::Sender).
    pub const fn inner(&self) -> &mpsc::Sender<T> {
        &self.sender
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `try_send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
        match self.sender.try_send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
        match self.sender.send(value).await {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for MeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`OwnedPermit`](mpsc::OwnedPermit) that updates metrics accounting
/// when sending
#[derive(Debug)]
pub struct OwnedPermit<T> {
    permit: mpsc::OwnedPermit<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> OwnedP


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use crate::Metrics;

use metrics::Counter;
use reth_primitives_traits::InMemorySize;
use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};
use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};
use tokio_util::sync::{PollSendError, PollSender};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.
pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.
pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>) {
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> MeteredSender<T> {
    /// Creates a new [`MeteredSender`] wrapping around the provided [Sender](mpsc::Sender)
    pub fn new(sender: mpsc::Sender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve_owned`.
    pub fn try_reserve_owned(self) -> Result<OwnedPermit<T>, TrySendError<Self>> {
        let Self { sender, metrics } = self;
        sender.try_reserve_owned().map(|permit| OwnedPermit::new(permit, metrics.clone())).map_err(
            |err| match err {
                TrySendError::Full(sender) => TrySendError::Full(Self { sender, metrics }),
                TrySendError::Closed(sender) => TrySendError::Closed(Self { sender, metrics }),
            },
        )
    }

    /// Waits to acquire a permit to send a message and return owned permit.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve_owned`.
    pub async fn reserve_owned(self) -> Result<OwnedPermit<T>, SendError<()>> {
        self.sender.reserve_owned().await.map(|permit| OwnedPermit::new(permit, self.metrics))
    }

    /// Waits to acquire a permit to send a message.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve`.
    pub async fn reserve(&self) -> Result<Permit<'_, T>, SendError<()>> {
        self.sender.reserve().await.map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve`.
    pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
        self.sender.try_reserve().map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Returns the underlying [Sender](mpsc::Sender).
    pub const fn inner(&self) -> &mpsc::Sender<T> {
        &self.sender
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `try_send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
        match self.sender.try_send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
        match self.sender.send(value).await {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for MeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`OwnedPermit`](mpsc::OwnedPermit) that updates metrics accounting
/// when sending
#[derive(Debug)]
pub struct OwnedPermit<T> {
    permit: mpsc::OwnedPermit<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> OwnedPermit<T> {
    /// Cr


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use crate::Metrics;
use futures::Stream;

use reth_primitives_traits::InMemorySize;
use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};
use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};
use tokio_util::sync::{PollSendError, PollSender};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.
pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.
pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>) {
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> MeteredSender<T> {
    /// Creates a new [`MeteredSender`] wrapping around the provided [Sender](mpsc::Sender)
    pub fn new(sender: mpsc::Sender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve_owned`.
    pub fn try_reserve_owned(self) -> Result<OwnedPermit<T>, TrySendError<Self>> {
        let Self { sender, metrics } = self;
        sender.try_reserve_owned().map(|permit| OwnedPermit::new(permit, metrics.clone())).map_err(
            |err| match err {
                TrySendError::Full(sender) => TrySendError::Full(Self { sender, metrics }),
                TrySendError::Closed(sender) => TrySendError::Closed(Self { sender, metrics }),
            },
        )
    }

    /// Waits to acquire a permit to send a message and return owned permit.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve_owned`.
    pub async fn reserve_owned(self) -> Result<OwnedPermit<T>, SendError<()>> {
        self.sender.reserve_owned().await.map(|permit| OwnedPermit::new(permit, self.metrics))
    }

    /// Waits to acquire a permit to send a message.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve`.
    pub async fn reserve(&self) -> Result<Permit<'_, T>, SendError<()>> {
        self.sender.reserve().await.map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve`.
    pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
        self.sender.try_reserve().map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Returns the underlying [Sender](mpsc::Sender).
    pub const fn inner(&self) -> &mpsc::Sender<T> {
        &self.sender
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `try_send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
        match self.sender.try_send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
        match self.sender.send(value).await {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for MeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`OwnedPermit`](mpsc::OwnedPermit) that updates metrics accounting
/// when sending
#[derive(Debug)]
pub struct OwnedPermit<T> {
    permit: mpsc::OwnedPermit<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> OwnedPermit<T> {
    /// Creates a new [`OwnedPe


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use crate::Metrics;
use futures::Stream;
use metrics::Counter;

use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};
use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};
use tokio_util::sync::{PollSendError, PollSender};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.
pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.
pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>) {
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> MeteredSender<T> {
    /// Creates a new [`MeteredSender`] wrapping around the provided [Sender](mpsc::Sender)
    pub fn new(sender: mpsc::Sender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve_owned`.
    pub fn try_reserve_owned(self) -> Result<OwnedPermit<T>, TrySendError<Self>> {
        let Self { sender, metrics } = self;
        sender.try_reserve_owned().map(|permit| OwnedPermit::new(permit, metrics.clone())).map_err(
            |err| match err {
                TrySendError::Full(sender) => TrySendError::Full(Self { sender, metrics }),
                TrySendError::Closed(sender) => TrySendError::Closed(Self { sender, metrics }),
            },
        )
    }

    /// Waits to acquire a permit to send a message and return owned permit.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve_owned`.
    pub async fn reserve_owned(self) -> Result<OwnedPermit<T>, SendError<()>> {
        self.sender.reserve_owned().await.map(|permit| OwnedPermit::new(permit, self.metrics))
    }

    /// Waits to acquire a permit to send a message.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve`.
    pub async fn reserve(&self) -> Result<Permit<'_, T>, SendError<()>> {
        self.sender.reserve().await.map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve`.
    pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
        self.sender.try_reserve().map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Returns the underlying [Sender](mpsc::Sender).
    pub const fn inner(&self) -> &mpsc::Sender<T> {
        &self.sender
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `try_send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
        match self.sender.try_send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
        match self.sender.send(value).await {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for MeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`OwnedPermit`](mpsc::OwnedPermit) that updates metrics accounting
/// when sending
#[derive(Debug)]
pub struct OwnedPermit<T> {
    permit: mpsc::OwnedPermit<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> OwnedPermit<T> {
    /// Creates a new [`OwnedPermit`] wrapping the provided [`m


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use crate::Metrics;
use futures::Stream;
use metrics::Counter;
use reth_primitives_traits::InMemorySize;

use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};

use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};
use tokio_util::sync::{PollSendError, PollSender};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.
pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.
pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>) {
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> MeteredSender<T> {
    /// Creates a new [`MeteredSender`] wrapping around the provided [Sender](mpsc::Sender)
    pub fn new(sender: mpsc::Sender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve_owned`.
    pub fn try_reserve_owned(self) -> Result<OwnedPermit<T>, TrySendError<Self>> {
        let Self { sender, metrics } = self;
        sender.try_reserve_owned().map(|permit| OwnedPermit::new(permit, metrics.clone())).map_err(
            |err| match err {
                TrySendError::Full(sender) => TrySendError::Full(Self { sender, metrics }),
                TrySendError::Closed(sender) => TrySendError::Closed(Self { sender, metrics }),
            },
        )
    }

    /// Waits to acquire a permit to send a message and return owned permit.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve_owned`.
    pub async fn reserve_owned(self) -> Result<OwnedPermit<T>, SendError<()>> {
        self.sender.reserve_owned().await.map(|permit| OwnedPermit::new(permit, self.metrics))
    }

    /// Waits to acquire a permit to send a message.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve`.
    pub async fn reserve(&self) -> Result<Permit<'_, T>, SendError<()>> {
        self.sender.reserve().await.map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve`.
    pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
        self.sender.try_reserve().map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Returns the underlying [Sender](mpsc::Sender).
    pub const fn inner(&self) -> &mpsc::Sender<T> {
        &self.sender
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `try_send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
        match self.sender.try_send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
        match self.sender.send(value).await {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for MeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`OwnedPermit`](mpsc::OwnedPermit) that updates metrics accounting
/// when sending
#[derive(Debug)]
pub struct OwnedPermit<T> {
    permit: mpsc::OwnedPermit<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> OwnedPermit<T> {
    /// Creates a new [`OwnedPermit`] wrapping the provided [`mpsc::OwnedPermit`] with given metrics
    /// handle.
    pub const fn new(permit: mpsc::


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use crate::Metrics;
use futures::Stream;
use metrics::Counter;
use reth_primitives_traits::InMemorySize;
use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};

use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};

use tokio_util::sync::{PollSendError, PollSender};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.
pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.
pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>) {
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> MeteredSender<T> {
    /// Creates a new [`MeteredSender`] wrapping around the provided [Sender](mpsc::Sender)
    pub fn new(sender: mpsc::Sender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve_owned`.
    pub fn try_reserve_owned(self) -> Result<OwnedPermit<T>, TrySendError<Self>> {
        let Self { sender, metrics } = self;
        sender.try_reserve_owned().map(|permit| OwnedPermit::new(permit, metrics.clone())).map_err(
            |err| match err {
                TrySendError::Full(sender) => TrySendError::Full(Self { sender, metrics }),
                TrySendError::Closed(sender) => TrySendError::Closed(Self { sender, metrics }),
            },
        )
    }

    /// Waits to acquire a permit to send a message and return owned permit.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve_owned`.
    pub async fn reserve_owned(self) -> Result<OwnedPermit<T>, SendError<()>> {
        self.sender.reserve_owned().await.map(|permit| OwnedPermit::new(permit, self.metrics))
    }

    /// Waits to acquire a permit to send a message.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve`.
    pub async fn reserve(&self) -> Result<Permit<'_, T>, SendError<()>> {
        self.sender.reserve().await.map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve`.
    pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
        self.sender.try_reserve().map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Returns the underlying [Sender](mpsc::Sender).
    pub const fn inner(&self) -> &mpsc::Sender<T> {
        &self.sender
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `try_send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
        match self.sender.try_send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
        match self.sender.send(value).await {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for MeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`OwnedPermit`](mpsc::OwnedPermit) that updates metrics accounting
/// when sending
#[derive(Debug)]
pub struct OwnedPermit<T> {
    permit: mpsc::OwnedPermit<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> OwnedPermit<T> {
    /// Creates a new [`OwnedPermit`] wrapping the provided [`mpsc::OwnedPermit`] with given metrics
    /// handle.
    pub const fn new(permit: mpsc::OwnedPermit<T>, metrics: MeteredSenderMetrics) -> Self {
        Self { permit, metrics }
    }

    /// Sends a


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use crate::Metrics;
use futures::Stream;
use metrics::Counter;
use reth_primitives_traits::InMemorySize;
use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};
use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.
pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.
pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>) {
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> MeteredSender<T> {
    /// Creates a new [`MeteredSender`] wrapping around the provided [Sender](mpsc::Sender)
    pub fn new(sender: mpsc::Sender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve_owned`.
    pub fn try_reserve_owned(self) -> Result<OwnedPermit<T>, TrySendError<Self>> {
        let Self { sender, metrics } = self;
        sender.try_reserve_owned().map(|permit| OwnedPermit::new(permit, metrics.clone())).map_err(
            |err| match err {
                TrySendError::Full(sender) => TrySendError::Full(Self { sender, metrics }),
                TrySendError::Closed(sender) => TrySendError::Closed(Self { sender, metrics }),
            },
        )
    }

    /// Waits to acquire a permit to send a message and return owned permit.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve_owned`.
    pub async fn reserve_owned(self) -> Result<OwnedPermit<T>, SendError<()>> {
        self.sender.reserve_owned().await.map(|permit| OwnedPermit::new(permit, self.metrics))
    }

    /// Waits to acquire a permit to send a message.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve`.
    pub async fn reserve(&self) -> Result<Permit<'_, T>, SendError<()>> {
        self.sender.reserve().await.map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve`.
    pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
        self.sender.try_reserve().map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Returns the underlying [Sender](mpsc::Sender).
    pub const fn inner(&self) -> &mpsc::Sender<T> {
        &self.sender
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `try_send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
        match self.sender.try_send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
        match self.sender.send(value).await {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for MeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`OwnedPermit`](mpsc::OwnedPermit) that updates metrics accounting
/// when sending
#[derive(Debug)]
pub struct OwnedPermit<T> {
    permit: mpsc::OwnedPermit<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> OwnedPermit<T> {
    /// Creates a new [`OwnedPermit`] wrapping the provided [`mpsc::OwnedPermit`] with given metrics
    /// handle.
    pub const fn new(permit: mpsc::OwnedPermit<T>, metrics: MeteredSenderMetrics) -> Self {
        Self { permit, metrics }
    }

    /// Sends a value using the reserved capacity and update metrics accordingly.


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use crate::Metrics;
use futures::Stream;
use metrics::Counter;
use reth_primitives_traits::InMemorySize;
use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};
use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};
use tokio_util::sync::{PollSendError, PollSender};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.

pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.
pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>) {
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetr


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use crate::Metrics;
use futures::Stream;
use metrics::Counter;
use reth_primitives_traits::InMemorySize;
use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};
use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};
use tokio_util::sync::{PollSendError, PollSender};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.
pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>)

{
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.
pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>) {
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> MeteredSender<T> {
    /// Creates a new [`MeteredSender`] wrapping around the provided [Sender](mpsc::Sender)
    pub fn new(sender: mpsc::Sender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve_owned`.
    pub fn try_reserve_owned(self) -> Result<OwnedPermit<T>, TrySendError<Self>> {
        let Self { sender, metrics } = self;
        sender.try_reserve_owned().map(|permit| OwnedPermit::new(permit, metrics.clone())).map_err(
            |err| match err {
                TrySendError::Full(sender) => TrySendError::Full(Self { sender, metrics }),
                TrySendError::Closed(sender) => TrySendError::Closed(Self { sender, metrics }),
            },
        )
    }

    /// Waits to acquire a permit to send a message and return owned permit.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve_owned`.
    pub async fn reserve_owned(self) -> Result<OwnedPermit<T>, SendError<()>> {
        self.sender.reserve_owned().await.map(|permit| OwnedPermit::new(permit, self.metrics))
    }

    /// Waits to acquire a permit to send a message.
    ///
    /// See also [Sender](mpsc::Sender)'s `reserve`.
    pub async fn reserve(&self) -> Result<Permit<'_, T>, SendError<()>> {
        self.sender.reserve().await.map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve`.
    pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
        self.sender.try_reserve().map(|permit| Permit::new(permit, &self.metrics))
    }

    /// Returns the underlying [Sender](mpsc::Sender).
    pub const fn inner(&self) -> &mpsc::Sender<T> {
        &self.sender
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `try_send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
        match self.sender.try_send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }

    /// Calls the underlying [Sender](mpsc::Sender)'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
        match self.sender.send(value).await {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for MeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`OwnedPermit`](mpsc::OwnedPermit) that updates metrics accounting
/// when sending
#[derive(Debug)]
pub struct OwnedPermit<T> {
    permit: mpsc::OwnedPermit<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> OwnedPermit<T> {
    /// Creates a new [`OwnedPermit`] wrapping the provided [`mpsc::OwnedPermit`] with given metrics
    /// handle.
    pub const fn new(permit: mpsc::OwnedPermit<T>, metrics: MeteredSenderMetrics) -> Self {
        Self { permit, metrics }
    }

    /// Sends a value using the reserved capacity and update metrics accordingly.
    pub fn send(self, value: T) -> MeteredSender<T> {
        let Self { permit, metrics } = self;
        metrics.messages_sent_total.increment(1);
        MeteredSender { sender: permit.send(value), metrics }
    }
}

/// A wrapper type around [Permit](mpsc::Permit) that updates metrics accounting
/// when sendi


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use crate::Metrics;
use futures::Stream;
use metrics::Counter;
use reth_primitives_traits::InMemorySize;
use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};
use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};
use tokio_util::sync::{PollSendError, PollSender};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.
pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.

pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>) {
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> MeteredSender<T> {
    /// Creates a new [`MeteredSender`] wrapping around the provided [Sender](mpsc::Sender)
    pub fn new(sender: mpsc::Sender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// S


//! Support for metering senders. Facilitates debugging by exposing metrics for number of messages
//! sent, number of errors, etc.

use crate::Metrics;
use futures::Stream;
use metrics::Counter;
use reth_primitives_traits::InMemorySize;
use std::{
    pin::Pin,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
    task::{ready, Context, Poll},
};
use tokio::sync::mpsc::{
    self,
    error::{SendError, TryRecvError, TrySendError},
};
use tokio_util::sync::{PollSendError, PollSender};

/// Wrapper around [`mpsc::unbounded_channel`] that returns a new unbounded metered channel.
pub fn metered_unbounded_channel<T>(
    scope: &'static str,
) -> (UnboundedMeteredSender<T>, UnboundedMeteredReceiver<T>) {
    let (tx, rx) = mpsc::unbounded_channel();
    (UnboundedMeteredSender::new(tx, scope), UnboundedMeteredReceiver::new(rx, scope))
}

/// Wrapper around [`mpsc::channel`] that returns a new bounded metered channel with the given
/// buffer size.
pub fn metered_channel<T>(
    buffer: usize,
    scope: &'static str,
) -> (MeteredSender<T>, MeteredReceiver<T>)

{
    let (tx, rx) = mpsc::channel(buffer);
    (MeteredSender::new(tx, scope), MeteredReceiver::new(rx, scope))
}

/// A wrapper type around [`UnboundedSender`](mpsc::UnboundedSender) that updates metrics on send.
#[derive(Debug)]
pub struct UnboundedMeteredSender<T> {
    /// The [`UnboundedSender`](mpsc::UnboundedSender) that this wraps around
    sender: mpsc::UnboundedSender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> UnboundedMeteredSender<T> {
    /// Creates a new [`UnboundedMeteredSender`] wrapping around the provided
    /// [`mpsc::UnboundedSender`] that updates metrics on send.
    pub fn new(sender: mpsc::UnboundedSender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Calls the underlying [`mpsc::UnboundedSender`]'s `send`, incrementing the appropriate
    /// metrics depending on the result.
    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
        match self.sender.send(message) {
            Ok(()) => {
                self.metrics.messages_sent_total.increment(1);
                Ok(())
            }
            Err(error) => {
                self.metrics.send_errors_total.increment(1);
                Err(error)
            }
        }
    }
}

impl<T> Clone for UnboundedMeteredSender<T> {
    fn clone(&self) -> Self {
        Self { sender: self.sender.clone(), metrics: self.metrics.clone() }
    }
}

/// A wrapper type around [`UnboundedReceiver`](mpsc::UnboundedReceiver) that updates metrics on
/// receive.
#[derive(Debug)]
pub struct UnboundedMeteredReceiver<T> {
    /// The [`UnboundedReceiver`](mpsc::UnboundedReceiver) that this wraps around
    receiver: mpsc::UnboundedReceiver<T>,
    /// Holds metrics for this type
    metrics: MeteredReceiverMetrics,
}

// === impl MeteredReceiver ===

impl<T> UnboundedMeteredReceiver<T> {
    /// Creates a new [`UnboundedMeteredReceiver`] wrapping around the provided
    /// [Receiver](mpsc::UnboundedReceiver)
    pub fn new(receiver: mpsc::UnboundedReceiver<T>, scope: &'static str) -> Self {
        Self { receiver, metrics: MeteredReceiverMetrics::new(scope) }
    }

    /// Receives the next value for this receiver.
    pub async fn recv(&mut self) -> Option<T> {
        let msg = self.receiver.recv().await;
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        msg
    }

    /// Tries to receive the next value for this receiver.
    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
        let msg = self.receiver.try_recv()?;
        self.metrics.messages_received_total.increment(1);
        Ok(msg)
    }

    /// Closes the receiving half of a channel without dropping it.
    pub fn close(&mut self) {
        self.receiver.close();
    }

    /// Polls to receive the next message on this channel.
    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
        let msg = ready!(self.receiver.poll_recv(cx));
        if msg.is_some() {
            self.metrics.messages_received_total.increment(1);
        }
        Poll::Ready(msg)
    }
}

impl<T> Stream for UnboundedMeteredReceiver<T> {
    type Item = T;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.poll_recv(cx)
    }
}

/// A wrapper type around [Sender](mpsc::Sender) that updates metrics on send.
#[derive(Debug)]
pub struct MeteredSender<T> {
    /// The [Sender](mpsc::Sender) that this wraps around
    sender: mpsc::Sender<T>,
    /// Holds metrics for this type
    metrics: MeteredSenderMetrics,
}

impl<T> MeteredSender<T> {
    /// Creates a new [`MeteredSender`] wrapping around the provided [Sender](mpsc::Sender)
    pub fn new(sender: mpsc::Sender<T>, scope: &'static str) -> Self {
        Self { sender, metrics: MeteredSenderMetrics::new(scope) }
    }

    /// Tries to acquire a permit to send a message without waiting.
    ///
    /// See also [Sender](mpsc::Sender)'s `try_reserve_owned`.