Skip to content

Commit d8048ca

Browse files
committed
feat: return list of errors in new format to worker
1 parent 469aea6 commit d8048ca

File tree

6 files changed

+260
-82
lines changed

6 files changed

+260
-82
lines changed

Cargo.lock

Lines changed: 43 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

post-compute/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ zip = "4.0.0"
3030
logtest = "2.0.0"
3131
mockall = "0.13.1"
3232
once_cell = "1.21.3"
33+
rstest = "0.26.1"
3334
serial_test = "3.2.0"
3435
temp-env = "0.3.6"
3536
tempfile = "3.20.0"

post-compute/src/api/worker_api.rs

Lines changed: 25 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,6 @@ use crate::compute::{
55
};
66
use log::error;
77
use 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
///
@@ -121,17 +85,17 @@ 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
///
13195
/// match client.send_exit_cause_for_post_compute_stage(
13296
/// "authorization_token",
13397
/// "0x123456789abcdef",
134-
/// &exit_message,
98+
/// &exit_causes,
13599
/// ) {
136100
/// Ok(()) => println!("Exit cause reported successfully"),
137101
/// Err(error) => eprintln!("Failed to report exit cause: {}", error),
@@ -141,14 +105,14 @@ impl WorkerApiClient {
141105
&self,
142106
authorization: &str,
143107
chain_task_id: &str,
144-
exit_cause: &ExitMessage,
108+
exit_causes: &[ReplicateStatusCause],
145109
) -> Result<(), ReplicateStatusCause> {
146110
let url = format!("{}/compute/post/{chain_task_id}/exit", 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) => {
@@ -266,30 +230,24 @@ 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 should_serialize_list_of_exit_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 related environment variable is missing"}]"#;
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 should_serialize_single_exit_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

@@ -320,9 +278,7 @@ mod tests {
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"))
328284
.and(path(format!("/compute/post/{CHAIN_TASK_ID}/exit")))
@@ -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);
340295
worker_api_client.send_exit_cause_for_post_compute_stage(
341296
CHALLENGE,
342297
CHAIN_TASK_ID,
343-
&exit_message,
298+
&exit_causes,
344299
)
345300
})
346301
.await
@@ -367,13 +322,12 @@ mod tests {
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);
373327
worker_api_client.send_exit_cause_for_post_compute_stage(
374328
CHALLENGE,
375329
CHAIN_TASK_ID,
376-
&exit_message,
330+
&exit_causes,
377331
)
378332
})
379333
.await

post-compute/src/compute/app_runner.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::api::worker_api::{ExitMessage, WorkerApiClient};
1+
use crate::api::worker_api::WorkerApiClient;
22
use crate::compute::{
33
computed_file::{
44
ComputedFile, build_result_digest_in_computed_file, read_computed_file, sign_computed_file,
@@ -35,7 +35,7 @@ pub trait PostComputeRunnerInterface {
3535
&self,
3636
authorization: &str,
3737
chain_task_id: &str,
38-
exit_message: &ExitMessage,
38+
exit_causes: &[ReplicateStatusCause],
3939
) -> Result<(), ReplicateStatusCause>;
4040
fn send_computed_file(&self, computed_file: &ComputedFile) -> Result<(), ReplicateStatusCause>;
4141
}
@@ -103,10 +103,10 @@ impl PostComputeRunnerInterface for DefaultPostComputeRunner {
103103
&self,
104104
authorization: &str,
105105
chain_task_id: &str,
106-
exit_message: &ExitMessage,
106+
exit_causes: &[ReplicateStatusCause],
107107
) -> Result<(), ReplicateStatusCause> {
108108
self.worker_api_client
109-
.send_exit_cause_for_post_compute_stage(authorization, chain_task_id, exit_message)
109+
.send_exit_cause_for_post_compute_stage(authorization, chain_task_id, exit_causes)
110110
}
111111

112112
fn send_computed_file(&self, computed_file: &ComputedFile) -> Result<(), ReplicateStatusCause> {
@@ -189,9 +189,9 @@ pub fn start_with_runner<R: PostComputeRunnerInterface>(runner: &R) -> ExitMode
189189
}
190190
};
191191

192-
let exit_message = ExitMessage::from(&exit_cause);
192+
let exit_causes = vec![exit_cause.clone()];
193193

194-
match runner.send_exit_cause(&authorization, &chain_task_id, &exit_message) {
194+
match runner.send_exit_cause(&authorization, &chain_task_id, &exit_causes) {
195195
Ok(()) => ExitMode::ReportedFailure,
196196
Err(_) => {
197197
error!("Failed to report exit cause [exitCause:{exit_cause}]");
@@ -302,7 +302,7 @@ mod tests {
302302
&self,
303303
_authorization: &str,
304304
_chain_task_id: &str,
305-
_exit_message: &ExitMessage,
305+
_exit_causes: &[ReplicateStatusCause],
306306
) -> Result<(), ReplicateStatusCause> {
307307
if self.send_exit_cause_success {
308308
Ok(())

0 commit comments

Comments
 (0)