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}