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