Skip to main content

emergent_client/
lib.rs

1//! Emergent Client Library
2//!
3//! This crate provides the client-side SDK for building Sources, Handlers, and Sinks
4//! that connect to the Emergent workflow engine.
5//!
6//! # Primitives
7//!
8//! Emergent uses three primitives that define how clients interact with the message bus:
9//!
10//! - [`EmergentSource`] - Publishes messages to the workflow (ingress from external world)
11//! - [`EmergentHandler`] - Subscribes to and publishes messages (transformation/processing)
12//! - [`EmergentSink`] - Subscribes to messages (egress to external world)
13//!
14//! # Example: Source
15//!
16//! ```rust,ignore
17//! use emergent_client::{EmergentSource, EmergentMessage};
18//! use serde_json::json;
19//!
20//! #[tokio::main]
21//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
22//!     let source = EmergentSource::connect("my_source").await?;
23//!
24//!     let message = EmergentMessage::new("timer.tick")
25//!         .with_payload(json!({"sequence": 1}));
26//!
27//!     source.publish(message).await?;
28//!     Ok(())
29//! }
30//! ```
31//!
32//! # Example: Handler
33//!
34//! ```rust,ignore
35//! use emergent_client::{EmergentHandler, EmergentMessage};
36//! use serde_json::json;
37//!
38//! #[tokio::main]
39//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
40//!     let handler = EmergentHandler::connect("my_handler").await?;
41//!     let mut stream = handler.subscribe(&["timer.tick"]).await?;
42//!
43//!     while let Some(msg) = stream.next().await {
44//!         // Process and publish transformed message
45//!         let output = EmergentMessage::new("timer.processed")
46//!             .with_causation_id(msg.id())
47//!             .with_payload(json!({"original": msg.payload}));
48//!         handler.publish(output).await?;
49//!     }
50//!     Ok(())
51//! }
52//! ```
53//!
54//! # Example: Sink
55//!
56//! ```rust,ignore
57//! use emergent_client::EmergentSink;
58//!
59//! #[tokio::main]
60//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
61//!     let sink = EmergentSink::connect("my_sink").await?;
62//!     let mut stream = sink.subscribe(&["timer.processed"]).await?;
63//!
64//!     while let Some(msg) = stream.next().await {
65//!         println!("Received: {} - {:?}", msg.message_type, msg.payload);
66//!     }
67//!     Ok(())
68//! }
69//! ```
70
71mod connection;
72mod error;
73pub mod helpers;
74mod message;
75pub mod prelude;
76mod stream;
77mod subscribe;
78pub mod types;
79
80pub use connection::{
81    EmergentHandler, EmergentSink, EmergentSource, TopologyPrimitive, TopologyState,
82};
83pub use error::ClientError;
84pub use message::{EmergentMessage, create_message};
85pub use stream::MessageStream;
86pub use subscribe::IntoSubscription;
87
88/// Result type for client operations.
89pub type Result<T> = std::result::Result<T, ClientError>;
90
91/// Discovery information about the engine.
92#[derive(Debug, Clone)]
93pub struct DiscoveryInfo {
94    /// Available message types that can be subscribed to.
95    pub message_types: Vec<String>,
96    /// List of connected primitives.
97    pub primitives: Vec<PrimitiveInfo>,
98}
99
100/// Information about a registered primitive.
101#[derive(Debug, Clone)]
102pub struct PrimitiveInfo {
103    /// Name of the primitive.
104    pub name: String,
105    /// Type of primitive (Source, Handler, Sink).
106    pub kind: String,
107}