Skip to content

Commit b557b61

Browse files
committed
refactor: Support no return type for stubbed activities
1 parent 578ec5c commit b557b61

10 files changed

Lines changed: 90 additions & 72 deletions

File tree

crates/testing/test-programs/stub/activity/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ impl Guest for Component {
99
fn foo(_arg: String) -> String {
1010
todo!()
1111
}
12+
13+
fn noret() {}
1214
}

crates/testing/test-programs/stub/activity/wit/testing_stub-activity-obelisk-ext/stub-activity-ext.wit

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,7 @@ interface activity {
55

66
foo-submit: func(join-set-id: borrow<join-set-id>, arg: string) -> execution-id;
77
foo-await-next: func(join-set-id: borrow<join-set-id>) -> result<tuple<execution-id, string>, tuple<execution-id, execution-error>>;
8+
9+
noret-submit: func(join-set-id: borrow<join-set-id>) -> execution-id;
10+
noret-await-next: func(join-set-id: borrow<join-set-id>) -> result<execution-id, tuple<execution-id, execution-error>>;
811
}

crates/testing/test-programs/stub/activity/wit/testing_stub-activity-obelisk-stub/stub-activity-stub.wit

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@ interface activity {
44
use obelisk:types/execution@1.1.0.{execution-id, stub-error};
55

66
foo-stub: func(execution-id: execution-id, return-value: string) -> result<_, stub-error>;
7+
8+
noret-stub: func(execution-id: execution-id) -> result<_, stub-error>;
9+
710
}

crates/testing/test-programs/stub/activity/wit/testing_stub-activity/stub-activity.wit

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ package testing:stub-activity;
22

33
interface activity {
44
foo: func(arg: string) -> string;
5+
6+
noret: func();
57
}

crates/testing/test-programs/stub/workflow/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,8 @@ impl Guest for Component {
2424
fn submit_await(arg: String) -> String {
2525
activity::foo(&arg)
2626
}
27+
28+
fn noret_submit_await() {
29+
activity::noret();
30+
}
2731
}

crates/testing/test-programs/stub/workflow/wit/deps/testing_stub-workflow/stub-workflow.wit

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ package testing:stub-workflow;
33
interface workflow {
44
submit-stub-await: func(arg: string) -> string;
55
submit-await: func(arg: string) -> string;
6+
7+
noret-submit-await: func();
68
}

crates/utils/src/snapshots/obeli_sk_utils__wit__tests__wit_should_contain_extensions@test_programs_stub_activity.wasm_wit.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ package wasi:filesystem@0.2.3 {
217217
package testing:stub-activity {
218218
interface activity {
219219
foo: func(arg: string) -> string;
220+
221+
noret: func();
220222
}
221223
}
222224

@@ -230,6 +232,10 @@ package testing:stub-activity-obelisk-ext {
230232
foo-submit: func(join-set-id: borrow<join-set-id>, arg: string) -> execution-id;
231233

232234
foo-await-next: func(join-set-id: borrow<join-set-id>) -> result<tuple<execution-id, string>, tuple<execution-id, execution-error>>;
235+
236+
noret-submit: func(join-set-id: borrow<join-set-id>) -> execution-id;
237+
238+
noret-await-next: func(join-set-id: borrow<join-set-id>) -> result<execution-id, tuple<execution-id, execution-error>>;
233239
}
234240
}
235241

@@ -239,5 +245,7 @@ package testing:stub-activity-obelisk-stub {
239245
use obelisk:types/execution@1.1.0.{execution-id, stub-error};
240246

241247
foo-stub: func(execution-id: execution-id, return-value: string) -> result<_, stub-error>;
248+
249+
noret-stub: func(execution-id: execution-id) -> result<_, stub-error>;
242250
}
243251
}

crates/webui/src/components/execution_stub_submit_page.rs

Lines changed: 59 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,19 @@ pub fn execution_stub_result_page(
3232
<p>{"function not found"}</p>
3333
};
3434
};
35-
let (fn_detail, _) = app_state
35+
let maybe_return_type = &app_state
3636
.ffqns_to_details
3737
.get(ffqn)
38-
.expect("`ffqns_to_details` and `comopnents_by_exported_ifc` must be consistent, based from `ListComponentsResponse`");
38+
.expect("`ffqns_to_details` and `comopnents_by_exported_ifc` must be consistent, based from `ListComponentsResponse`").0
39+
.return_type;
3940

4041
let component_id = component
4142
.component_id
4243
.clone()
4344
.expect("`component_id` is sent");
4445
// disable the submit button while a request is inflight
4546
let request_processing_state = use_state(|| false);
46-
let input_state = use_state(NodeRef::default);
47+
let input_ref = use_node_ref();
4748
let err_state = use_state(|| None);
4849

4950
let wit_state: UseStateHandle<Option<String>> = use_state(|| None);
@@ -73,28 +74,31 @@ pub fn execution_stub_result_page(
7374

7475
let on_submit = {
7576
let request_processing_state = request_processing_state.clone();
76-
let input_state = input_state.clone();
7777
let err_state = err_state.clone();
7878
let ffqn = ffqn.clone();
7979
let navigator = use_navigator().unwrap();
8080
let execution_id = execution_id.clone();
81+
let input_ref = input_ref.clone();
82+
let is_ret_some = maybe_return_type.is_some();
8183
Callback::from(move |e: SubmitEvent| {
8284
e.prevent_default(); // prevent form submission
83-
let input = input_state
84-
.deref()
85-
.cast::<HtmlInputElement>()
86-
.unwrap()
87-
.value();
88-
match serde_json::from_str::<serde_json::Value>(&input) {
89-
Ok(_) => {
90-
debug!("serde ok")
91-
}
92-
Err(serde_err) => {
93-
error!("Cannot serialize input - {serde_err:?}");
94-
err_state.set(Some(format!("cannot serialize input - {serde_err}")));
95-
return;
96-
}
85+
let input = if is_ret_some {
86+
let input = input_ref.cast::<HtmlInputElement>().unwrap().value();
87+
match serde_json::from_str::<serde_json::Value>(&input) {
88+
Ok(_) => {
89+
debug!("serde ok")
90+
}
91+
Err(serde_err) => {
92+
error!("Cannot serialize input - {serde_err:?}");
93+
err_state.set(Some(format!("cannot serialize input - {serde_err}")));
94+
return;
95+
}
96+
};
97+
Some(input)
98+
} else {
99+
None
97100
};
101+
98102
debug!("Input: {input:?}");
99103
{
100104
err_state.set(None);
@@ -117,7 +121,7 @@ pub fn execution_stub_result_page(
117121
let response = client
118122
.stub(grpc_client::StubRequest {
119123
execution_id: Some(execution_id.clone()),
120-
return_value: Some(prost_wkt_types::Any {
124+
return_value: input.map(|input| prost_wkt_types::Any {
121125
type_url: format!("urn:obelisk:json:retval:{ffqn}"),
122126
value: input.into_bytes(),
123127
}),
@@ -139,39 +143,38 @@ pub fn execution_stub_result_page(
139143
};
140144

141145
// Validate on first render
142-
use_effect_with(input_state.deref().clone(), {
146+
use_effect_with((), {
143147
let err_state = err_state.clone();
144-
let fn_detail = fn_detail.clone();
145-
let input_state = input_state.clone();
148+
let input_ref = input_ref.clone();
149+
let maybe_return_type = maybe_return_type.clone();
146150
move |_| {
147-
debug!("Validating the form after first render");
148-
let input = input_state
149-
.deref()
150-
.cast::<HtmlInputElement>()
151-
.unwrap()
152-
.value();
153-
if let Err(err) = validate_response(&fn_detail, &input) {
154-
err_state.set(Some(err));
155-
} else {
156-
err_state.set(None);
151+
if let Some(return_type) = maybe_return_type {
152+
debug!("Validating the form after first render");
153+
let input = input_ref.cast::<HtmlInputElement>().unwrap().value();
154+
if let Err(err) = validate_response(&return_type, &input) {
155+
err_state.set(Some(err));
156+
} else {
157+
err_state.set(None);
158+
}
157159
}
158160
}
159161
});
162+
160163
let oninput = {
161-
let input_state = input_state.clone();
162-
let err_state = err_state.clone();
163-
let fn_detail = fn_detail.clone();
164-
move |_| {
165-
let input = input_state
166-
.deref()
167-
.cast::<HtmlInputElement>()
168-
.unwrap()
169-
.value();
170-
if let Err(err) = validate_response(&fn_detail, &input) {
171-
err_state.set(Some(err));
172-
} else {
173-
err_state.set(None);
174-
}
164+
if let Some(return_type) = maybe_return_type {
165+
let err_state = err_state.clone();
166+
let return_type = return_type.clone();
167+
let input_ref = input_ref.clone();
168+
Some(move |_| {
169+
let input = input_ref.cast::<HtmlInputElement>().unwrap().value();
170+
if let Err(err) = validate_response(&return_type, &input) {
171+
err_state.set(Some(err));
172+
} else {
173+
err_state.set(None);
174+
}
175+
})
176+
} else {
177+
None
175178
}
176179
};
177180

@@ -180,12 +183,6 @@ pub fn execution_stub_result_page(
180183
.as_ref()
181184
.map(|wit| wit_highlighter::print_interface_with_single_fn(wit, ffqn));
182185

183-
let wit_type = fn_detail
184-
.return_type
185-
.as_ref()
186-
.expect("TODO")
187-
.wit_type
188-
.as_str();
189186
html! {<>
190187
<header>
191188
<h1>{"Stub execution result"}</h1>
@@ -202,10 +199,14 @@ pub fn execution_stub_result_page(
202199
</h3>
203200
</header>
204201
<form id="execution-stub-result-form" onsubmit = {on_submit }>
205-
<p>
206-
<label for="input">{wit_type}</label>
207-
<input id="input" type="text" ref={input_state.deref()} oninput = {oninput}/>
208-
</p>
202+
if let Some(return_type) = maybe_return_type {
203+
<p>
204+
<label for="input">{return_type.wit_type.as_str()}</label>
205+
<input id="input" type="text" ref={input_ref.clone()} oninput = {oninput}/>
206+
</p>
207+
} else {
208+
<p>{"(no return value)"}</p>
209+
}
209210
<button type="submit" disabled={*request_processing_state}>
210211
{"Submit response"}
211212
</button>
@@ -220,18 +221,10 @@ pub fn execution_stub_result_page(
220221
</>}
221222
}
222223

223-
fn validate_response(
224-
function_detail: &grpc_client::FunctionDetail,
225-
value: &str,
226-
) -> Result<(), String> {
224+
fn validate_response(return_type: &grpc_client::WitType, value: &str) -> Result<(), String> {
227225
match serde_json::from_str::<serde_json::Value>(value) {
228226
Ok(value) => {
229-
let type_wrapper = function_detail
230-
.return_type
231-
.as_ref()
232-
.expect("TODO")
233-
.type_wrapper
234-
.as_str();
227+
let type_wrapper = return_type.type_wrapper.as_str();
235228
let type_and_value_json = format!("{{\"type\": {type_wrapper}, \"value\": {value}}}");
236229
match serde_json::from_str::<WastValWithType>(&type_and_value_json) {
237230
Ok(_) => Ok(()),

src/args.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ pub(crate) enum Execution {
148148
execution_id: ExecutionIdDerived,
149149
/// Return value encoded as an JSON
150150
#[arg(value_name = "RETVAL")]
151-
return_value: String,
151+
return_value: Option<String>,
152152
},
153153
Get {
154154
/// Follow the status stream until the execution finishes.

src/command/execution.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,18 @@ pub(crate) async fn submit(
7171
pub(crate) async fn stub(
7272
mut client: ExecutionRepositoryClient,
7373
execution_id: ExecutionIdDerived,
74-
return_value: String,
74+
return_value: Option<String>,
7575
) -> anyhow::Result<()> {
7676
let execution_id = ExecutionId::Derived(execution_id);
7777
// Make sure `return_value` is a JSON string.
78-
79-
serde_json::from_str::<serde_json::Value>(&return_value)
80-
.context("`RETURN_VALUE` must be a JSON-encoded string")?;
78+
if let Some(return_value) = &return_value {
79+
serde_json::from_str::<serde_json::Value>(return_value)
80+
.context("`RETURN_VALUE` must be a JSON-encoded string")?;
81+
}
8182
client
8283
.stub(tonic::Request::new(grpc_gen::StubRequest {
8384
execution_id: Some(execution_id.clone().into()),
84-
return_value: Some(prost_wkt_types::Any {
85+
return_value: return_value.map(|return_value| prost_wkt_types::Any {
8586
type_url: "urn:obelisk:json:retval:TBD".to_string(),
8687
value: return_value.into_bytes(),
8788
}),

0 commit comments

Comments
 (0)