@@ -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