@@ -5,42 +5,6 @@ use crate::compute::{
55} ; 
66use  log:: error; 
77use  reqwest:: { blocking:: Client ,  header:: AUTHORIZATION } ; 
8- use  serde:: Serialize ; 
9- 
10- /// Represents payload that can be sent to the worker API to report the outcome of the 
11- /// post‑compute stage. 
12- /// 
13- /// The JSON structure expected by the REST endpoint is: 
14- /// ```json 
15- /// { 
16- ///   "cause": "<ReplicateStatusCause as string>" 
17- /// } 
18- /// ``` 
19- /// 
20- /// # Arguments 
21- /// 
22- /// * `cause` - A reference to the ReplicateStatusCause indicating why the post-compute operation exited 
23- /// 
24- /// # Example 
25- /// 
26- /// ```rust 
27- /// use tee_worker_post_compute::{ 
28- ///     api::worker_api::ExitMessage, 
29- ///     compute::errors::ReplicateStatusCause, 
30- /// }; 
31- /// 
32- /// let exit_message = ExitMessage::from(&ReplicateStatusCause::PostComputeInvalidTeeSignature); 
33- /// ``` 
34- #[ derive( Serialize ,  Debug ) ]  
35- pub  struct  ExitMessage < ' a >  { 
36-     pub  cause :  & ' a  ReplicateStatusCause , 
37- } 
38- 
39- impl < ' a >  From < & ' a  ReplicateStatusCause >  for  ExitMessage < ' a >  { 
40-     fn  from ( cause :  & ' a  ReplicateStatusCause )  -> Self  { 
41-         Self  {  cause } 
42-     } 
43- } 
448
459/// Thin wrapper around a [`Client`] that knows how to reach the iExec worker API. 
4610/// 
@@ -96,21 +60,21 @@ impl WorkerApiClient {
9660        Self :: new ( & base_url) 
9761    } 
9862
99-     /// Sends an  exit cause  for a post-compute operation to the Worker API. 
63+     /// Sends exit causes  for a post-compute operation to the Worker API. 
10064/// 
101- /// This method reports the exit cause  of a post-compute operation to the Worker API, 
65+ /// This method reports the exit causes  of a post-compute operation to the Worker API, 
10266/// which can be used for tracking and debugging purposes. 
10367/// 
10468/// # Arguments 
10569/// 
10670/// * `authorization` - The authorization token to use for the API request 
107- /// * `chain_task_id` - The chain task ID for which to report the exit cause  
108- /// * `exit_cause ` - The exit cause  to report 
71+ /// * `chain_task_id` - The chain task ID for which to report the exit causes  
72+ /// * `exit_causes ` - The exit causes  to report 
10973/// 
11074/// # Returns 
11175/// 
112- /// * `Ok(())` - If the exit cause was  successfully reported 
113- /// * `Err(ReplicateStatusCause)` - If the exit cause  could not be reported due to an HTTP error 
76+ /// * `Ok(())` - If the exit causes were  successfully reported 
77+ /// * `Err(ReplicateStatusCause)` - If the exit causes  could not be reported due to an HTTP error 
11478/// 
11579/// # Errors 
11680/// 
@@ -121,34 +85,34 @@ impl WorkerApiClient {
12185/// 
12286/// ```rust 
12387/// use tee_worker_post_compute::{ 
124- ///     api::worker_api::{ExitMessage,  WorkerApiClient} , 
88+ ///     api::worker_api::WorkerApiClient, 
12589///     compute::errors::ReplicateStatusCause, 
12690/// }; 
12791/// 
12892/// let client = WorkerApiClient::new("http://worker:13100"); 
129- /// let exit_message  = ExitMessage::from(& ReplicateStatusCause::PostComputeInvalidTeeSignature) ; 
93+ /// let exit_causes  = vec![ ReplicateStatusCause::PostComputeInvalidTeeSignature] ; 
13094/// 
131- /// match client.send_exit_cause_for_post_compute_stage ( 
95+ /// match client.send_exit_causes_for_post_compute_stage ( 
13296///     "authorization_token", 
13397///     "0x123456789abcdef", 
134- ///     &exit_message , 
98+ ///     &exit_causes , 
13599/// ) { 
136- ///     Ok(()) => println!("Exit cause  reported successfully"), 
137- ///     Err(error) => eprintln!("Failed to report exit cause : {}", error), 
100+ ///     Ok(()) => println!("Exit causes  reported successfully"), 
101+ ///     Err(error) => eprintln!("Failed to report exit causes : {}", error), 
138102/// } 
139103/// ``` 
140- pub  fn  send_exit_cause_for_post_compute_stage ( 
104+ pub  fn  send_exit_causes_for_post_compute_stage ( 
141105        & self , 
142106        authorization :  & str , 
143107        chain_task_id :  & str , 
144-         exit_cause :  & ExitMessage , 
108+         exit_causes :  & [ ReplicateStatusCause ] , 
145109    )  -> Result < ( ) ,  ReplicateStatusCause >  { 
146-         let  url = format ! ( "{}/compute/post/{chain_task_id}/exit" ,  self . base_url) ; 
110+         let  url = format ! ( "{}/compute/post/{chain_task_id}/exit-causes " ,  self . base_url) ; 
147111        match  self 
148112            . client 
149113            . post ( & url) 
150114            . header ( AUTHORIZATION ,  authorization) 
151-             . json ( exit_cause ) 
115+             . json ( exit_causes ) 
152116            . send ( ) 
153117        { 
154118            Ok ( response)  => { 
@@ -158,13 +122,13 @@ impl WorkerApiClient {
158122                    let  status = response. status ( ) ; 
159123                    let  body = response. text ( ) . unwrap_or_default ( ) ; 
160124                    error ! ( 
161-                         "Failed to send exit cause  to worker: [status:{status:?}, body:{body:#?}]" 
125+                         "Failed to send exit causes  to worker: [status:{status:?}, body:{body:#?}]" 
162126                    ) ; 
163127                    Err ( ReplicateStatusCause :: PostComputeFailedUnknownIssue ) 
164128                } 
165129            } 
166130            Err ( e)  => { 
167-                 error ! ( "An error occured while sending exit cause  to worker: {e}" ) ; 
131+                 error ! ( "An error occured while sending exit causes  to worker: {e}" ) ; 
168132                Err ( ReplicateStatusCause :: PostComputeFailedUnknownIssue ) 
169133            } 
170134        } 
@@ -266,36 +230,30 @@ mod tests {
266230    const  CHALLENGE :  & str  = "challenge" ; 
267231    const  CHAIN_TASK_ID :  & str  = "0x123456789abcdef" ; 
268232
269-     // region ExitMessage()  
233+     // region serialize List of ReplicateStatusCause  
270234    #[ test]  
271-     fn  should_serialize_exit_message ( )  { 
272-         let  causes = [ 
273-             ( 
274-                 ReplicateStatusCause :: PostComputeInvalidTeeSignature , 
275-                 "POST_COMPUTE_INVALID_TEE_SIGNATURE" , 
276-             ) , 
277-             ( 
278-                 ReplicateStatusCause :: PostComputeWorkerAddressMissing , 
279-                 "POST_COMPUTE_WORKER_ADDRESS_MISSING" , 
280-             ) , 
281-             ( 
282-                 ReplicateStatusCause :: PostComputeFailedUnknownIssue , 
283-                 "POST_COMPUTE_FAILED_UNKNOWN_ISSUE" , 
284-             ) , 
235+     fn  replicate_status_cause_serializes_as_json_array_when_multiple_causes ( )  { 
236+         let  causes = vec ! [ 
237+             ReplicateStatusCause :: PostComputeInvalidTeeSignature , 
238+             ReplicateStatusCause :: PostComputeWorkerAddressMissing , 
285239        ] ; 
240+         let  serialized = to_string ( & causes) . expect ( "Failed to serialize" ) ; 
241+         let  expected = r#"[{"cause":"POST_COMPUTE_INVALID_TEE_SIGNATURE","message":"Invalid TEE signature"},{"cause":"POST_COMPUTE_WORKER_ADDRESS_MISSING","message":"Worker address not found in TEE session"}]"# ; 
242+         assert_eq ! ( serialized,  expected) ; 
243+     } 
286244
287-          for   ( cause ,  message )   in  causes  { 
288-              let  exit_message =  ExitMessage :: from ( & cause ) ; 
289-              let  serialized  = to_string ( & exit_message ) . expect ( "Failed to serialize" ) ; 
290-              let  expected  = format ! ( "{{ \" cause \" : \" {message} \" }} ") ; 
291-              assert_eq ! ( serialized ,  expected ) ; 
292-         } 
245+     # [ test ] 
246+     fn   replicate_status_cause_serializes_as_json_array_when_single_cause ( )   { 
247+         let  causes  = vec ! [ ReplicateStatusCause :: PostComputeFailedUnknownIssue ] ; 
248+         let  serialized  = to_string ( & causes ) . expect ( "Failed to serialize ") ; 
249+         let  expected =  r#"[{"cause":"POST_COMPUTE_FAILED_UNKNOWN_ISSUE","message":"Unexpected error occurred"}]"# ; 
250+         assert_eq ! ( serialized ,  expected ) ; 
293251    } 
294252    // endregion 
295253
296254    // region get_worker_api_client 
297255    #[ test]  
298-     fn  should_get_worker_api_client_with_env_var ( )  { 
256+     fn  from_env_creates_client_with_custom_url_when_env_var_set ( )  { 
299257        with_vars ( 
300258            vec ! [ ( WorkerHostEnvVar . name( ) ,  Some ( "custom-worker-host:9999" ) ) ] , 
301259            || { 
@@ -306,26 +264,24 @@ mod tests {
306264    } 
307265
308266    #[ test]  
309-     fn  should_get_worker_api_client_without_env_var ( )  { 
267+     fn  from_env_creates_client_with_default_url_when_env_var_missing ( )  { 
310268        with_vars ( vec ! [ ( WorkerHostEnvVar . name( ) ,  None :: <& str >) ] ,  || { 
311269            let  client = WorkerApiClient :: from_env ( ) ; 
312270            assert_eq ! ( client. base_url,  format!( "http://{DEFAULT_WORKER_HOST}" ) ) ; 
313271        } ) ; 
314272    } 
315273    // endregion 
316274
317-     // region send_exit_cause_for_post_compute_stage () 
275+     // region send_exit_causes_for_post_compute_stage () 
318276    #[ tokio:: test]  
319-     async  fn  should_send_exit_cause ( )  { 
277+     async  fn  send_exit_causes_for_post_compute_stage_succeeds_when_server_responds_ok ( )  { 
320278        let  mock_server = MockServer :: start ( ) . await ; 
321279        let  server_url = mock_server. uri ( ) ; 
322280
323-         let  expected_body = json ! ( { 
324-             "cause" :  ReplicateStatusCause :: PostComputeInvalidTeeSignature , 
325-         } ) ; 
281+         let  expected_body = json ! ( [ ReplicateStatusCause :: PostComputeInvalidTeeSignature , ] ) ; 
326282
327283        Mock :: given ( method ( "POST" ) ) 
328-             . and ( path ( format ! ( "/compute/post/{CHAIN_TASK_ID}/exit" ) ) ) 
284+             . and ( path ( format ! ( "/compute/post/{CHAIN_TASK_ID}/exit-causes " ) ) ) 
329285            . and ( header ( "Authorization" ,  CHALLENGE ) ) 
330286            . and ( body_json ( & expected_body) ) 
331287            . respond_with ( ResponseTemplate :: new ( 200 ) ) 
@@ -334,13 +290,12 @@ mod tests {
334290            . await ; 
335291
336292        let  result = tokio:: task:: spawn_blocking ( move  || { 
337-             let  exit_message =
338-                 ExitMessage :: from ( & ReplicateStatusCause :: PostComputeInvalidTeeSignature ) ; 
293+             let  exit_causes = vec ! [ ReplicateStatusCause :: PostComputeInvalidTeeSignature ] ; 
339294            let  worker_api_client = WorkerApiClient :: new ( & server_url) ; 
340-             worker_api_client. send_exit_cause_for_post_compute_stage ( 
295+             worker_api_client. send_exit_causes_for_post_compute_stage ( 
341296                CHALLENGE , 
342297                CHAIN_TASK_ID , 
343-                 & exit_message , 
298+                 & exit_causes , 
344299            ) 
345300        } ) 
346301        . await 
@@ -351,7 +306,7 @@ mod tests {
351306
352307    #[ tokio:: test]  
353308    #[ serial]  
354-     async  fn  should_not_send_exit_cause ( )  { 
309+     async  fn  send_exit_causes_for_post_compute_stage_fails_when_server_returns_404 ( )  { 
355310        { 
356311            let  mut  logger = TEST_LOGGER . lock ( ) . unwrap ( ) ; 
357312            while  logger. pop ( ) . is_some ( )  { } 
@@ -360,20 +315,19 @@ mod tests {
360315        let  server_url = mock_server. uri ( ) ; 
361316
362317        Mock :: given ( method ( "POST" ) ) 
363-             . and ( path ( format ! ( "/compute/post/{CHAIN_TASK_ID}/exit" ) ) ) 
318+             . and ( path ( format ! ( "/compute/post/{CHAIN_TASK_ID}/exit-causes " ) ) ) 
364319            . respond_with ( ResponseTemplate :: new ( 404 ) ) 
365320            . expect ( 1 ) 
366321            . mount ( & mock_server) 
367322            . await ; 
368323
369324        let  result = tokio:: task:: spawn_blocking ( move  || { 
370-             let  exit_message =
371-                 ExitMessage :: from ( & ReplicateStatusCause :: PostComputeFailedUnknownIssue ) ; 
325+             let  exit_causes = vec ! [ ReplicateStatusCause :: PostComputeFailedUnknownIssue ] ; 
372326            let  worker_api_client = WorkerApiClient :: new ( & server_url) ; 
373-             worker_api_client. send_exit_cause_for_post_compute_stage ( 
327+             worker_api_client. send_exit_causes_for_post_compute_stage ( 
374328                CHALLENGE , 
375329                CHAIN_TASK_ID , 
376-                 & exit_message , 
330+                 & exit_causes , 
377331            ) 
378332        } ) 
379333        . await 
@@ -402,7 +356,7 @@ mod tests {
402356
403357    // region send_computed_file_to_host() 
404358    #[ tokio:: test]  
405-     async  fn  should_send_computed_file_successfully ( )  { 
359+     async  fn  send_computed_file_to_host_succeeds_when_server_responds_ok ( )  { 
406360        let  mock_server = MockServer :: start ( ) . await ; 
407361        let  server_uri = mock_server. uri ( ) ; 
408362
@@ -437,7 +391,7 @@ mod tests {
437391
438392    #[ tokio:: test]  
439393    #[ serial]  
440-     async  fn  should_fail_send_computed_file_on_server_error ( )  { 
394+     async  fn  send_computed_file_to_host_fails_when_server_returns_500 ( )  { 
441395        { 
442396            let  mut  logger = TEST_LOGGER . lock ( ) . unwrap ( ) ; 
443397            while  logger. pop ( ) . is_some ( )  { } 
@@ -491,7 +445,7 @@ mod tests {
491445
492446    #[ tokio:: test]  
493447    #[ serial]  
494-     async  fn  should_handle_invalid_chain_task_id_in_url ( )  { 
448+     async  fn  send_computed_file_to_host_fails_when_chain_task_id_invalid ( )  { 
495449        { 
496450            let  mut  logger = TEST_LOGGER . lock ( ) . unwrap ( ) ; 
497451            while  logger. pop ( ) . is_some ( )  { } 
@@ -532,7 +486,7 @@ mod tests {
532486    } 
533487
534488    #[ tokio:: test]  
535-     async  fn  should_send_computed_file_with_minimal_data ( )  { 
489+     async  fn  send_computed_file_to_host_succeeds_when_minimal_data_provided ( )  { 
536490        let  mock_server = MockServer :: start ( ) . await ; 
537491        let  server_uri = mock_server. uri ( ) ; 
538492
0 commit comments