Repository: paritytech/substrate
File: client/network/src/service/out_events.rs (Rust)

Code before:
/// sync on drop. If someone adds a `#[derive(Clone)]` below, it is **wrong**.
pub struct Sender {
	inner: async_channel::Sender<Event>,
	/// Name to identify the channel (e.g., in Prometheus and logs).
	name: &'static str,
	/// Threshold queue size to generate an error message in the logs.
	queue_size_warning: usize,
	/// We generate the error message only once to not spam the logs.
	warning_fired: bool,
	/// Backtrace of a place where the channel was created.
	creation_backtrace: Backtrace,
	/// Clone of [`Receiver::metrics`]. Will be initialized when [`Sender`] is added to
	/// [`OutChannels`] with `OutChannels::push()`.
	metrics: Option<Metrics>,
}

impl fmt::Debug for Sender {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		f.debug_tuple("Sender").finish()
	}
}

impl Drop for Sender {
	fn drop(&mut self) {
		let metrics = self.metrics.clone();
		if let Some(metrics) = metrics.as_ref() {
			metrics.num_channels.with_label_values(&[self.name]).dec();
		}
	}
}

/// Receiving side of a channel.
pub struct Receiver {
	inner: async_channel::Receiver<Event>,
	name: &'static str,
	/// Initially contains `None`, and will be set to a value once the corresponding [`Sender`]
	/// is assigned to an instance of [`OutChannels`].
	metrics: Option<Metrics>,
}

impl Stream for Receiver {
	type Item = Event;

	fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Event>> {
		if let Some(ev) = ready!(Pin::new(&mut self.inner).poll_next(cx)) {
			let metrics = self.metrics.clone();
			match metrics.as_ref() {
				Some(metrics) => metrics.event_out(&ev, self.name),
				None => (), // no registry
			}
			Poll::Ready(Some(ev))

Review comment (suggestion):
```suggestion
		if let Some(metrics) = self.metrics.as_ref() {
```

Code after:
	/// The warning has not been fired yet.
	NotFired,
	/// The warning has been fired, and the channel is full
	FiredFull,
	/// The warning has been fired and the channel is not full anymore.
	FiredFree,
}

/// Sending side of a channel.
///
/// Must be associated with an [`OutChannels`] before anything can be sent on it
///
/// > **Note**: Contrary to regular channels, this `Sender` is purposefully designed to not
/// implement the `Clone` trait e.g. in Order to not complicate the logic keeping the metrics in
/// sync on drop. If someone adds a `#[derive(Clone)]` below, it is **wrong**.
pub struct Sender {
	inner: async_channel::Sender<Event>,
	/// Name to identify the channel (e.g., in Prometheus and logs).
	name: &'static str,
	/// Threshold queue size to generate an error message in the logs.
	queue_size_warning: usize,
	/// We generate the error message only once to not spam the logs after the first error.
	/// Subsequently we indicate channel fullness on debug level.
	warning_fired: SenderWarningState,
	/// Backtrace of a place where the channel was created.
	creation_backtrace: Backtrace,
	/// Clone of [`Receiver::metrics`]. Will be initialized when [`Sender`] is added to
	/// [`OutChannels`] with `OutChannels::push()`.
	metrics: Option<Metrics>,
}

impl fmt::Debug for Sender {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		f.debug_tuple("Sender").finish()
	}
}

impl Drop for Sender {
	fn drop(&mut self) {
		if let Some(metrics) = self.metrics.as_ref() {
			metrics.num_channels.with_label_values(&[self.name]).dec();
		}
	}
}

/// Receiving side of a channel.
pub struct Receiver {
	inner: async_channel::Receiver<Event>,
	name: &'static str,
	/// Initially contains `None`, and will be set to a value once the corresponding [`Sender`]
	/// is assigned to an instance of [`OutChannels`].