up_rust/communication/
notification.rs

1/********************************************************************************
2 * Copyright (c) 2024 Contributors to the Eclipse Foundation
3 *
4 * See the NOTICE file(s) distributed with this work for additional
5 * information regarding copyright ownership.
6 *
7 * This program and the accompanying materials are made available under the
8 * terms of the Apache License Version 2.0 which is available at
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * SPDX-License-Identifier: Apache-2.0
12 ********************************************************************************/
13
14use std::{error::Error, fmt::Display, sync::Arc};
15
16use async_trait::async_trait;
17
18use crate::communication::RegistrationError;
19use crate::{UListener, UStatus, UUri};
20
21use super::{CallOptions, UPayload};
22
23/// An error indicating a problem with sending a notification to another uEntity.
24// [impl->dsn~communication-layer-api-declaration~1]
25#[derive(Debug)]
26pub enum NotificationError {
27    /// Indicates that the given message cannot be sent because it is not a [valid Notification message](crate::NotificationValidator).
28    InvalidArgument(String),
29    /// Indicates an unspecific error that occurred at the Transport Layer while trying to send a notification.
30    NotifyError(UStatus),
31}
32
33#[cfg(not(tarpaulin_include))]
34impl Display for NotificationError {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        match self {
37            NotificationError::InvalidArgument(s) => f.write_str(s.as_str()),
38            NotificationError::NotifyError(s) => {
39                f.write_fmt(format_args!("failed to send notification: {s}"))
40            }
41        }
42    }
43}
44
45impl Error for NotificationError {}
46
47/// A client for sending Notification messages to a uEntity.
48///
49/// Please refer to the
50/// [Communication Layer API Specifications](https://github.com/eclipse-uprotocol/up-spec/blob/main/up-l2/api.adoc).
51// [impl->dsn~communication-layer-api-declaration~1]
52#[cfg_attr(any(test, feature = "test-util"), mockall::automock)]
53#[async_trait]
54pub trait Notifier: Send + Sync {
55    /// Sends a notification to a uEntity.
56    ///
57    /// # Arguments
58    ///
59    /// * `resource_id` - The (local) resource identifier representing the origin of the notification.
60    /// * `destination` - A URI representing the uEntity that the notification should be sent to.
61    /// * `call_options` - Options to include in the notification message.
62    /// * `payload` - The payload to include in the notification message.
63    ///
64    /// # Errors
65    ///
66    /// Returns an error if the given message is not a valid
67    /// [uProtocol Notification message](`crate::NotificationValidator`).
68    async fn notify(
69        &self,
70        resource_id: u16,
71        destination: &UUri,
72        call_options: CallOptions,
73        payload: Option<UPayload>,
74    ) -> Result<(), NotificationError>;
75
76    /// Starts listening to a notification topic.
77    ///
78    /// More than one handler can be registered for the same topic.
79    /// The same handler can be registered for multiple topics.
80    ///
81    /// # Arguments
82    ///
83    /// * `topic` - The topic to listen to. The topic must not contain any wildcards.
84    /// * `listener` - The handler to invoke for each notification that has been sent on the topic.
85    ///
86    /// # Errors
87    ///
88    /// Returns an error if the listener cannot be registered.
89    async fn start_listening(
90        &self,
91        topic: &UUri,
92        listener: Arc<dyn UListener>,
93    ) -> Result<(), RegistrationError>;
94
95    /// Deregisters a previously [registered handler](`Self::start_listening`) for listening to notifications.
96    ///
97    /// # Arguments
98    ///
99    /// * `topic` - The topic that the handler had been registered for.
100    /// * `listener` - The handler to unregister.
101    ///
102    /// # Errors
103    ///
104    /// Returns an error if the listener cannot be unregistered.
105    async fn stop_listening(
106        &self,
107        topic: &UUri,
108        listener: Arc<dyn UListener>,
109    ) -> Result<(), RegistrationError>;
110}