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}