@@ -2,12 +2,13 @@ use crate::ast::{Handler, Object, Service, ServiceInner, ServiceType, Workflow};
2
2
use proc_macro2:: TokenStream as TokenStream2 ;
3
3
use proc_macro2:: { Ident , Literal } ;
4
4
use quote:: { format_ident, quote, ToTokens } ;
5
- use syn:: { parse_quote , Attribute , ReturnType , Type , Visibility } ;
5
+ use syn:: { Attribute , PatType , Visibility } ;
6
6
7
7
pub ( crate ) struct ServiceGenerator < ' a > {
8
8
pub ( crate ) service_ty : ServiceType ,
9
9
pub ( crate ) restate_name : & ' a str ,
10
10
pub ( crate ) service_ident : & ' a Ident ,
11
+ pub ( crate ) client_ident : Ident ,
11
12
pub ( crate ) serve_ident : Ident ,
12
13
pub ( crate ) vis : & ' a Visibility ,
13
14
pub ( crate ) attrs : & ' a [ Attribute ] ,
@@ -20,6 +21,7 @@ impl<'a> ServiceGenerator<'a> {
20
21
service_ty,
21
22
restate_name : & s. restate_name ,
22
23
service_ident : & s. ident ,
24
+ client_ident : format_ident ! ( "{}Client" , s. ident) ,
23
25
serve_ident : format_ident ! ( "Serve{}" , s. ident) ,
24
26
vis : & s. vis ,
25
27
attrs : & s. attrs ,
@@ -50,8 +52,6 @@ impl<'a> ServiceGenerator<'a> {
50
52
..
51
53
} = self ;
52
54
53
- let unit_type: & Type = & parse_quote ! ( ( ) ) ;
54
-
55
55
let handler_fns = handlers
56
56
. iter ( )
57
57
. map (
@@ -66,13 +66,9 @@ impl<'a> ServiceGenerator<'a> {
66
66
( ServiceType :: Workflow , false ) => quote ! { :: restate_sdk:: prelude:: WorkflowContext } ,
67
67
} ;
68
68
69
- let output = match output {
70
- ReturnType :: Type ( _, ref ty) => ty. as_ref ( ) ,
71
- ReturnType :: Default => unit_type,
72
- } ;
73
69
quote ! {
74
70
#( #attrs ) *
75
- fn #ident( & self , context: #ctx, #( #args ) , * ) -> impl std:: future:: Future <Output =#output> + :: core:: marker:: Send ;
71
+ fn #ident( & self , context: #ctx, #( #args ) , * ) -> impl std:: future:: Future <Output =:: restate_sdk :: prelude :: HandlerResult < #output> > + :: core:: marker:: Send ;
76
72
}
77
73
} ,
78
74
) ;
@@ -223,6 +219,123 @@ impl<'a> ServiceGenerator<'a> {
223
219
}
224
220
}
225
221
}
222
+
223
+ fn struct_client ( & self ) -> TokenStream2 {
224
+ let & Self {
225
+ vis,
226
+ ref client_ident,
227
+ // service_ident,
228
+ ref service_ty,
229
+ ..
230
+ } = self ;
231
+
232
+ let key_field = match service_ty {
233
+ ServiceType :: Service => quote ! { } ,
234
+ ServiceType :: Object | ServiceType :: Workflow => quote ! {
235
+ key: String ,
236
+ } ,
237
+ } ;
238
+
239
+ let into_client_impl = match service_ty {
240
+ ServiceType :: Service => {
241
+ quote ! {
242
+ impl <' ctx> :: restate_sdk:: context:: IntoServiceClient <' ctx> for #client_ident<' ctx> {
243
+ fn create_client( ctx: & ' ctx :: restate_sdk:: endpoint:: ContextInternal ) -> Self {
244
+ Self { ctx }
245
+ }
246
+ }
247
+ }
248
+ }
249
+ ServiceType :: Object => quote ! {
250
+ impl <' ctx> :: restate_sdk:: context:: IntoObjectClient <' ctx> for #client_ident<' ctx> {
251
+ fn create_client( ctx: & ' ctx :: restate_sdk:: endpoint:: ContextInternal , key: String ) -> Self {
252
+ Self { ctx, key }
253
+ }
254
+ }
255
+ } ,
256
+ ServiceType :: Workflow => quote ! {
257
+ impl <' ctx> :: restate_sdk:: context:: IntoWorkflowClient <' ctx> for #client_ident<' ctx> {
258
+ fn create_client( ctx: & ' ctx :: restate_sdk:: endpoint:: ContextInternal , key: String ) -> Self {
259
+ Self { ctx, key }
260
+ }
261
+ }
262
+ } ,
263
+ } ;
264
+
265
+ quote ! {
266
+ /// Struct exposing the client to invoke [#service_ident] from another service.
267
+ #vis struct #client_ident<' ctx> {
268
+ ctx: & ' ctx :: restate_sdk:: endpoint:: ContextInternal ,
269
+ #key_field
270
+ }
271
+
272
+ #into_client_impl
273
+ }
274
+ }
275
+
276
+ fn impl_client ( & self ) -> TokenStream2 {
277
+ let & Self {
278
+ vis,
279
+ ref client_ident,
280
+ service_ident,
281
+ handlers,
282
+ restate_name,
283
+ service_ty,
284
+ ..
285
+ } = self ;
286
+
287
+ let service_literal = Literal :: string ( restate_name) ;
288
+
289
+ let handlers_fns = handlers. iter ( ) . map ( |handler| {
290
+ let handler_ident = & handler. ident ;
291
+ let handler_literal = Literal :: string ( & handler. restate_name ) ;
292
+
293
+ let argument = match & handler. arg {
294
+ None => quote ! { } ,
295
+ Some ( PatType {
296
+ ty, ..
297
+ } ) => quote ! { req: #ty }
298
+ } ;
299
+ let argument_ty = match & handler. arg {
300
+ None => quote ! { ( ) } ,
301
+ Some ( PatType {
302
+ ty, ..
303
+ } ) => quote ! { #ty }
304
+ } ;
305
+ let res_ty = & handler. output ;
306
+ let input = match & handler. arg {
307
+ None => quote ! { ( ) } ,
308
+ Some ( _) => quote ! { req }
309
+ } ;
310
+ let request_target = match service_ty {
311
+ ServiceType :: Service => quote ! {
312
+ :: restate_sdk:: context:: RequestTarget :: service( #service_literal, #handler_literal)
313
+ } ,
314
+ ServiceType :: Object => quote ! {
315
+ :: restate_sdk:: context:: RequestTarget :: object( #service_literal, & self . key, #handler_literal)
316
+ } ,
317
+ ServiceType :: Workflow => quote ! {
318
+ :: restate_sdk:: context:: RequestTarget :: workflow( #service_literal, & self . key, #handler_literal)
319
+ }
320
+ } ;
321
+
322
+ quote ! {
323
+ #vis fn #handler_ident( & self , #argument) -> :: restate_sdk:: context:: Request <' ctx, #argument_ty, #res_ty> {
324
+ self . ctx. request( #request_target, #input)
325
+ }
326
+ }
327
+ } ) ;
328
+
329
+ let doc_msg = format ! (
330
+ "Struct exposing the client to invoke [`{service_ident}`] from another service."
331
+ ) ;
332
+ quote ! {
333
+ #[ doc = #doc_msg]
334
+ impl <' ctx> #client_ident<' ctx> {
335
+ #( #handlers_fns ) *
336
+ }
337
+ }
338
+ }
226
339
}
227
340
228
341
impl < ' a > ToTokens for ServiceGenerator < ' a > {
@@ -232,6 +345,8 @@ impl<'a> ToTokens for ServiceGenerator<'a> {
232
345
self . struct_serve( ) ,
233
346
self . impl_service_for_serve( ) ,
234
347
self . impl_discoverable( ) ,
348
+ self . struct_client( ) ,
349
+ self . impl_client( ) ,
235
350
] ) ;
236
351
}
237
352
}
0 commit comments