Preview of the proposed up-rust native-frame-model branch (up-rust b6b99c6d, up-spec f0e9b17) — not released documentation. branch · write-up

up_rust/communication/
pubsub.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::sync::Arc;
15
16use async_trait::async_trait;
17use thiserror::Error;
18
19use crate::{
20    communication::{CallOptions, RegistrationError, SubscriptionStatus, UPayload},
21    UListener, UStatus, UUri,
22};
23
24/// An error indicating a problem with publishing a message to a topic.
25// [impl->dsn~communication-layer-api-declaration~1]
26#[derive(Debug, Error)]
27#[non_exhaustive]
28pub enum PubSubError {
29    /// Indicates that the given message cannot be sent because it is not a
30    /// [valid Publish message](crate::UAttributesValidators::Publish).
31    #[error("invalid argument: {0}")]
32    InvalidArgument(String),
33    /// Indicates an unspecific error that occurred at the Transport Layer while trying to publish a message.
34    #[error("failed to publish message: {0}")]
35    PublishError(Box<UStatus>),
36}
37
38/// A client for publishing messages to a topic.
39///
40/// Please refer to the
41/// [Communication Layer API Specifications](https://github.com/eclipse-uprotocol/up-spec/blob/main/up-l2/api.adoc).
42// [impl->dsn~communication-layer-api-declaration~1]
43#[async_trait]
44pub trait Publisher: Send + Sync {
45    /// Publishes a message to a topic.
46    ///
47    /// # Arguments
48    ///
49    /// * `resource_id` - The (local) resource ID of the topic to publish to.
50    /// * `call_options` - Options to include in the published message.
51    /// * `payload` - Payload to include in the published message.
52    ///
53    /// # Errors
54    ///
55    /// Returns an error if the message could not be published.
56    async fn publish(
57        &self,
58        resource_id: u16,
59        call_options: CallOptions,
60        payload: Option<UPayload>,
61    ) -> Result<(), PubSubError>;
62}
63
64// [impl->dsn~communication-layer-api-declaration~1]
65#[cfg_attr(any(test, feature = "test-util"), mockall::automock)]
66/// Callback invoked when a subscription's status changes.
67pub trait SubscriptionChangeHandler: Send + Sync {
68    /// Invoked for each update to the subscription status for a given topic.
69    ///
70    /// Implementations must not block the current thread.
71    ///
72    /// # Arguments
73    ///
74    /// * `topic` - The topic for which the subscription status has changed.
75    /// * `status` - The new status of the subscription.
76    fn on_subscription_change(&self, topic: UUri, new_status: SubscriptionStatus);
77}
78
79/// A client for subscribing to topics.
80///
81/// Please refer to the
82/// [Communication Layer API Specifications](https://github.com/eclipse-uprotocol/up-spec/blob/main/up-l2/api.adoc).
83// [impl->dsn~communication-layer-api-declaration~1]
84#[async_trait]
85pub trait Subscriber: Send + Sync {
86    /// Registers a handler to invoke for messages that have been published to a given topic.
87    ///
88    /// More than one handler can be registered for the same topic.
89    /// The same handler can be registered for multiple topics.
90    ///
91    /// # Arguments
92    ///
93    /// * `topic` - The topic to subscribe to. The topic must not contain any wildcards.
94    /// * `handler` - The handler to invoke for each message that has been published to the topic.
95    /// * `subscription_change_handler` - A handler to invoke for any subscription state changes for
96    ///                                   the given topic.
97    ///
98    /// # Errors
99    ///
100    /// Returns an error if the listener cannot be registered.
101    async fn subscribe(
102        &self,
103        topic: &UUri,
104        handler: Arc<dyn UListener>,
105        subscription_change_handler: Option<Arc<dyn SubscriptionChangeHandler>>,
106    ) -> Result<(), RegistrationError>;
107
108    /// Deregisters a previously [registered handler](`Self::subscribe`).
109    ///
110    /// # Arguments
111    ///
112    /// * `topic` - The topic that the handler had been registered for.
113    /// * `handler` - The handler to unregister.
114    ///
115    /// # Errors
116    ///
117    /// Returns an error if the listener cannot be unregistered.
118    async fn unsubscribe(
119        &self,
120        topic: &UUri,
121        handler: Arc<dyn UListener>,
122    ) -> Result<(), RegistrationError>;
123}