acton_core/traits/
broker.rs

1/*
2 * Copyright (c) 2024. Govcraft
3 *
4 * Licensed under either of
5 *   * Apache License, Version 2.0 (the "License");
6 *     you may not use this file except in compliance with the License.
7 *     You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8 *   * MIT license: http://opensource.org/licenses/MIT
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the applicable License for the specific language governing permissions and
14 * limitations under that License.
15 */
16
17use std::fmt::Debug;
18use std::future::Future;
19
20use async_trait::async_trait;
21
22use crate::message::BrokerRequest;
23use crate::prelude::ActonMessage;
24use crate::traits::AgentHandleInterface; // Needed for broadcast_sync default impl
25
26/// Defines the capability to broadcast messages to subscribers via the system broker.
27///
28/// This trait is typically implemented by types that have access to the central
29/// [`AgentBroker`](crate::common::AgentBroker), such as [`AgentHandle`](crate::common::AgentHandle).
30/// It provides methods for sending messages to the broker for distribution to all
31/// agents subscribed to that message type.
32#[async_trait]
33pub trait Broker: Clone + Debug + Default + Send + Sync + 'static { // Added Send + Sync + 'static
34    /// Asynchronously sends a message to the broker for broadcasting.
35    ///
36    /// The implementor should wrap the `message` in a [`BrokerRequest`] and send it
37    /// to the central `AgentBroker`.
38    ///
39    /// # Arguments
40    ///
41    /// * `message`: The message payload (must implement [`ActonMessage`]) to broadcast.
42    ///
43    /// # Returns
44    ///
45    /// A `Future` that completes once the broadcast request has been sent to the broker.
46    /// Completion does not guarantee delivery to subscribers.
47    fn broadcast(&self, message: impl ActonMessage) -> impl Future<Output = ()> + Send + Sync + '_;
48
49    /// Synchronously sends a message to the broker for broadcasting.
50    ///
51    /// **Warning:** This default implementation relies on [`OutboundEnvelope::reply`],
52    /// which internally spawns a blocking task and creates a new Tokio runtime.
53    /// This is generally **discouraged** and can lead to performance issues or deadlocks,
54    /// especially if called from within an existing asynchronous context. Prefer using
55    /// the asynchronous [`Broker::broadcast`] method where possible.
56    ///
57    /// This method requires the implementing type (`Self`) to also implement
58    /// [`AgentHandleInterface`] to use its `create_envelope` method.
59    ///
60    /// # Arguments
61    ///
62    /// * `message`: The message payload (must implement [`ActonMessage`]) to broadcast.
63    ///
64    /// # Returns
65    ///
66    /// A `Result` indicating success or failure of initiating the synchronous send.
67    /// It relies on the behavior of [`OutboundEnvelope::reply`], which might not
68    /// propagate all underlying errors from the actual send operation.
69    fn broadcast_sync(&self, message: impl ActonMessage) -> anyhow::Result<()>
70    where
71        Self: AgentHandleInterface + Sized, // Require AgentHandleInterface for default impl
72    {
73        // Create an envelope targeting the broker (using self's address, assuming self *is* the broker handle or has access)
74        // The recipient here is implicitly the broker itself when using reply on an envelope created from the broker handle.
75        let envelope = self.create_envelope(Some(self.reply_address()));
76        // Wrap the user message in a BrokerRequest before sending.
77        envelope.reply(BrokerRequest::new(message))?; // Uses the potentially problematic OutboundEnvelope::reply
78        Ok(())
79    }
80}