33
44//! Example demonstrating LocalClient functionality
55
6- use dynamo_runtime:: DistributedRuntime ;
7- use dynamo_runtime:: component:: register_local_engine;
8- use dynamo_runtime:: engine:: { AsyncEngine , async_trait} ;
6+ use dynamo_runtime:: component:: LocalClient ;
7+ use dynamo_runtime:: engine:: { AsyncEngine , AsyncEngineContextProvider , async_trait} ;
8+ use dynamo_runtime:: pipeline:: network:: Ingress ;
9+ use dynamo_runtime:: pipeline:: { Context , ManyOut , ResponseStream , SingleIn } ;
10+ use dynamo_runtime:: protocols:: annotated:: Annotated ;
11+ use dynamo_runtime:: { DistributedRuntime , Runtime , distributed:: DistributedConfig } ;
12+ use futures:: StreamExt ;
913use std:: sync:: Arc ;
1014
1115/// Simple test engine that echoes strings
1216struct SimpleEchoEngine ;
1317
1418#[ async_trait]
15- impl AsyncEngine < String , String , String > for SimpleEchoEngine {
16- async fn generate ( & self , request : String ) -> Result < String , String > {
17- println ! ( "Engine received: {}" , request) ;
18- Ok ( format ! ( "Echo: {}" , request) )
19+ impl AsyncEngine < SingleIn < String > , ManyOut < Annotated < String > > , anyhow:: Error > for SimpleEchoEngine {
20+ async fn generate (
21+ & self ,
22+ request : SingleIn < String > ,
23+ ) -> Result < ManyOut < Annotated < String > > , anyhow:: Error > {
24+ println ! ( "Engine received: {}" , * request) ;
25+
26+ let response = Annotated {
27+ data : Some ( format ! ( "Echo: {}" , * request) ) ,
28+ id : None ,
29+ event : None ,
30+ comment : None ,
31+ } ;
32+
33+ let context = request. context ( ) ;
34+
35+ // Create a simple stream that yields the response once
36+ let stream = futures:: stream:: once ( async move { response } ) ;
37+ Ok ( ResponseStream :: new ( Box :: pin ( stream) , context) )
1938 }
2039}
2140
@@ -28,16 +47,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
2847
2948 // Create runtime and DRT
3049 println ! ( "1. Creating runtime..." ) ;
31- let runtime = dynamo_runtime:: Runtime :: builder ( )
32- . app_name ( "local-client-demo" )
33- . build ( )
34- . await ?;
50+ let runtime = Runtime :: from_current ( ) ?;
3551
36- let config = dynamo_runtime :: DistributedConfig :: builder ( )
37- . etcd_config ( Default :: default ( ) )
38- . nats_config ( Default :: default ( ) )
39- . is_static ( true )
40- . build ( ) ? ;
52+ let config = DistributedConfig {
53+ etcd_config : Default :: default ( ) ,
54+ nats_config : Default :: default ( ) ,
55+ is_static : true ,
56+ } ;
4157
4258 let drt = DistributedRuntime :: new ( runtime, config) . await ?;
4359 println ! ( " ✓ Runtime created\n " ) ;
@@ -52,40 +68,51 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5268
5369 // Create and register an engine
5470 println ! ( "3. Creating and registering engine..." ) ;
55- let engine: Arc < dyn AsyncEngine < String , String , String > > = Arc :: new ( SimpleEchoEngine ) ;
71+ let engine: Arc < dyn AsyncEngine < SingleIn < String > , ManyOut < Annotated < String > > , anyhow:: Error > > =
72+ Arc :: new ( SimpleEchoEngine ) ;
73+
74+ // Wrap the engine in an Ingress to make it a PushWorkHandler
75+ let ingress = Ingress :: for_engine ( engine) ?;
5676
57- // Register the engine for local access
58- let key = register_local_engine ( & endpoint, engine. clone ( ) ) . await ?;
59- println ! ( " ✓ Registered engine with key: {}\n " , key) ;
77+ // Create the endpoint instance with the ingress as handler (setup phase)
78+ let _endpoint_instance = endpoint
79+ . endpoint_builder ( )
80+ . handler ( ingress)
81+ . create ( )
82+ . await ?;
83+ println ! ( " ✓ Engine registered automatically during endpoint creation\n " ) ;
6084
61- // Demonstrate direct local invocation
62- println ! ( "4. Testing direct local invocation..." ) ;
85+ // Create a LocalClient using the endpoint's convenience method
86+ println ! ( "4. Creating LocalClient..." ) ;
87+ let local_client: LocalClient < SingleIn < String > , ManyOut < Annotated < String > > , anyhow:: Error > =
88+ endpoint. local_client ( ) . await ?;
89+ println ! ( " ✓ LocalClient created successfully\n " ) ;
90+
91+ // Demonstrate local client usage
92+ println ! ( "5. Testing LocalClient invocation..." ) ;
6393 println ! ( " (This bypasses all network layers and invokes the engine directly)" ) ;
6494
65- // Direct invocation through the registered engine
66- let response = engine
67- . generate ( "Hello from direct call!" . to_string ( ) )
68- . await ?;
69- println ! ( " Response: {}\n " , response) ;
70-
71- // Show what LocalClient would do
72- println ! ( "5. LocalClient usage (conceptual):" ) ;
73- println ! ( " - LocalClient::from_endpoint(&endpoint) would retrieve the engine" ) ;
74- println ! ( " - local_client.generate(request) would call the engine directly" ) ;
75- println ! ( " - No network overhead, no etcd watching, no instance discovery\n " ) ;
76-
77- // Show the registered engines
78- println ! ( "6. Registry information:" ) ;
79- println ! ( " - Key format: namespace/component/endpoint" ) ;
80- println ! ( " - Registered key: {}" , key) ;
81- println ! ( " - Engine is type-erased as AnyAsyncEngine" ) ;
82- println ! ( " - LocalClient downcasts back to specific types\n " ) ;
83-
84- // Cleanup
85- println ! ( "7. Cleanup..." ) ;
86- drt. unregister_local_engine ( & key) . await ;
87- println ! ( " ✓ Unregistered engine\n " ) ;
88-
89- println ! ( "=== Demo Complete ===" ) ;
95+ // Create a request with context
96+ let request = Context :: new ( "Hello from LocalClient!" . to_string ( ) ) ;
97+
98+ // Generate response using the local client
99+ let mut response_stream = local_client. generate ( request) . await ?;
100+ let response = response_stream. next ( ) . await . expect ( "Expected response" ) ;
101+
102+ println ! ( " Request: Hello from LocalClient!" ) ;
103+ if let Some ( data) = & response. data {
104+ println ! ( " Response: {}" , data) ;
105+ }
106+ println ! ( ) ;
107+
108+ // Show the benefits
109+ println ! ( "6. LocalClient Benefits:" ) ;
110+ println ! ( " ✓ No network overhead" ) ;
111+ println ! ( " ✓ No etcd watching required" ) ;
112+ println ! ( " ✓ No instance discovery needed" ) ;
113+ println ! ( " ✓ Direct in-process engine invocation" ) ;
114+ println ! ( " ✓ Perfect for testing and local development\n " ) ;
115+
116+ println ! ( "Demo completed successfully!" ) ;
90117 Ok ( ( ) )
91118}
0 commit comments