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}