Skip to content

Commit c0f7a5c

Browse files
Sujay JayakarConvex, Inc.
Sujay Jayakar
authored and
Convex, Inc.
committed
feat(components): Make ActionOutcome component-aware (#25684)
GitOrigin-RevId: 4866b0099a837a062a3209fa74a4d0c09ee90493
1 parent 09ba23c commit c0f7a5c

File tree

9 files changed

+119
-56
lines changed

9 files changed

+119
-56
lines changed

crates/application/src/application_function_runner/mod.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,7 @@ impl<RT: Runtime> FunctionRouter<RT> {
305305
.await?;
306306

307307
let FunctionOutcome::Action(outcome) = outcome else {
308-
anyhow::bail!(
309-
"Calling an action returned an invalid outcome: {:?}",
310-
outcome
311-
)
308+
anyhow::bail!("Calling an action returned an invalid outcome")
312309
};
313310
Ok(outcome)
314311
}
@@ -1166,7 +1163,7 @@ impl<RT: Runtime> ApplicationFunctionRunner<RT> {
11661163
identity.into(),
11671164
self.runtime.clone(),
11681165
None,
1169-
)?,
1166+
),
11701167
environment: ModuleEnvironment::Invalid,
11711168
memory_in_mb: 0,
11721169
execution_time: Duration::from_secs(0),
@@ -1323,10 +1320,9 @@ impl<RT: Runtime> ApplicationFunctionRunner<RT> {
13231320
)
13241321
.await;
13251322
timer.finish();
1326-
let udf_path = path.as_root_udf_path()?.clone();
13271323
node_outcome_result.map(|node_outcome| {
13281324
let outcome = ActionOutcome {
1329-
udf_path,
1325+
path: path.clone(),
13301326
arguments: arguments.clone(),
13311327
identity: tx.inert_identity(),
13321328
unix_timestamp,
@@ -1360,7 +1356,7 @@ impl<RT: Runtime> ApplicationFunctionRunner<RT> {
13601356
inert_identity,
13611357
self.runtime.clone(),
13621358
udf_server_version,
1363-
)?;
1359+
);
13641360
Ok(ActionCompletion {
13651361
outcome,
13661362
execution_time: start.elapsed(),

crates/application/src/function_log.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,8 @@ impl HeapSize for FunctionExecutionPart {
311311
}
312312
}
313313

314-
#[derive(Debug, Clone)]
314+
#[derive(Clone)]
315+
#[cfg_attr(any(test, feature = "testing"), derive(Debug))]
315316
pub struct ActionCompletion {
316317
pub outcome: ActionOutcome,
317318
pub execution_time: Duration,
@@ -786,7 +787,7 @@ impl<RT: Runtime> FunctionExecutionLog<RT> {
786787
let unix_timestamp = self.rt.unix_timestamp();
787788
let completion = ActionCompletion {
788789
outcome: ActionOutcome {
789-
udf_path: path.into_root_udf_path()?,
790+
path,
790791
arguments,
791792
identity,
792793
unix_timestamp,
@@ -807,7 +808,19 @@ impl<RT: Runtime> FunctionExecutionLog<RT> {
807808
}
808809

809810
fn _log_action(&self, completion: ActionCompletion, usage: TrackUsage) {
810-
let udf_path = completion.outcome.udf_path.clone();
811+
let outcome = completion.outcome;
812+
let log_lines = completion.log_lines;
813+
let udf_path = match outcome.path.clone().into_root_udf_path() {
814+
Ok(udf_path) => udf_path,
815+
Err(_) => {
816+
tracing::warn!(
817+
"Skipping logging non-root action: {:?}:{:?}",
818+
outcome.path.component,
819+
outcome.path.udf_path
820+
);
821+
return;
822+
},
823+
};
811824
let aggregated = match usage {
812825
TrackUsage::Track(usage_tracker) => {
813826
let usage_stats = usage_tracker.gather_user_stats();
@@ -829,16 +842,13 @@ impl<RT: Runtime> FunctionExecutionLog<RT> {
829842
if udf_path.is_system() {
830843
return;
831844
}
832-
let outcome = completion.outcome;
833-
let log_lines = completion.log_lines;
834-
835845
let execution = FunctionExecution {
836846
params: UdfParams::Function {
837847
error: match outcome.result {
838848
Ok(_) => None,
839849
Err(e) => Some(e),
840850
},
841-
identifier: outcome.udf_path.clone(),
851+
identifier: udf_path,
842852
},
843853
unix_timestamp: self.rt.unix_timestamp(),
844854
execution_timestamp: outcome.unix_timestamp,

crates/isolate/src/environment/action/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ impl<RT: Runtime> ActionEnvironment<RT> {
617617
result.as_ref().ok().and_then(|r| r.as_ref().ok()),
618618
)?;
619619
let outcome = ActionOutcome {
620-
udf_path: path.into_root_udf_path()?,
620+
path,
621621
arguments,
622622
unix_timestamp: start_unix_timestamp,
623623
identity: self.identity.into(),

crates/isolate/src/environment/action/outcome.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use pb::{
2121
#[cfg(any(test, feature = "testing"))]
2222
use proptest::prelude::*;
2323
use serde_json::Value as JsonValue;
24-
use sync_types::CanonicalizedUdfPath;
2524
use value::ConvexValue;
2625

2726
use super::HttpActionResult;
@@ -34,10 +33,10 @@ use crate::{
3433
ValidatedPathAndArgs,
3534
};
3635

37-
#[derive(Debug, Clone)]
38-
#[cfg_attr(any(test, feature = "testing"), derive(PartialEq))]
36+
#[derive(Clone)]
37+
#[cfg_attr(any(test, feature = "testing"), derive(Debug, PartialEq))]
3938
pub struct ActionOutcome {
40-
pub udf_path: CanonicalizedUdfPath,
39+
pub path: CanonicalizedComponentFunctionPath,
4140
pub arguments: ConvexArray,
4241
pub identity: InertIdentity,
4342

@@ -59,16 +58,16 @@ impl ActionOutcome {
5958
identity: InertIdentity,
6059
rt: impl Runtime,
6160
udf_server_version: Option<semver::Version>,
62-
) -> anyhow::Result<Self> {
63-
Ok(ActionOutcome {
64-
udf_path: path.into_root_udf_path()?,
61+
) -> Self {
62+
ActionOutcome {
63+
path,
6564
arguments,
6665
identity,
6766
unix_timestamp: rt.unix_timestamp(),
6867
result: Err(js_error),
6968
syscall_trace: SyscallTrace::new(),
7069
udf_server_version,
71-
})
70+
}
7271
}
7372

7473
pub(crate) fn from_proto(
@@ -92,7 +91,7 @@ impl ActionOutcome {
9291
};
9392
let (path, arguments, udf_server_version) = path_and_args.consume();
9493
Ok(Self {
95-
udf_path: path.into_root_udf_path()?,
94+
path,
9695
arguments,
9796
identity,
9897
unix_timestamp: unix_timestamp
@@ -110,7 +109,7 @@ impl TryFrom<ActionOutcome> for ActionOutcomeProto {
110109

111110
fn try_from(
112111
ActionOutcome {
113-
udf_path: _,
112+
path: _,
114113
arguments: _,
115114
identity: _,
116115
unix_timestamp,
@@ -142,16 +141,16 @@ impl Arbitrary for ActionOutcome {
142141
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
143142
use proptest::prelude::*;
144143
(
145-
any::<CanonicalizedUdfPath>(),
144+
any::<CanonicalizedComponentFunctionPath>(),
146145
any::<ConvexArray>(),
147146
any::<InertIdentity>(),
148147
any::<UnixTimestamp>(),
149148
any::<Result<JsonPackedValue, JsError>>(),
150149
any::<SyscallTrace>(),
151150
)
152151
.prop_map(
153-
|(udf_path, arguments, identity, unix_timestamp, result, syscall_trace)| Self {
154-
udf_path,
152+
|(path, arguments, identity, unix_timestamp, result, syscall_trace)| Self {
153+
path,
155154
arguments,
156155
identity,
157156
unix_timestamp,
@@ -228,12 +227,12 @@ mod tests {
228227
#[test]
229228
fn test_action_udf_outcome_roundtrips(udf_outcome in any::<ActionOutcome>()) {
230229
let udf_outcome_clone = udf_outcome.clone();
231-
let udf_path = udf_outcome.udf_path.clone();
230+
let path = udf_outcome.path.clone();
232231
let arguments = udf_outcome.arguments.clone();
233232
let version = udf_outcome.udf_server_version.clone();
234233
let identity = udf_outcome_clone.identity.clone();
235234
let path_and_args = ValidatedPathAndArgs::new_for_tests(
236-
udf_path,
235+
path,
237236
arguments,
238237
version
239238
);

crates/isolate/src/environment/helpers/outcome.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ use crate::{
1818
/// A `UdfOutcome` represents a successful execution of a developer's function
1919
/// by our V8 layer. It slightly differs from `UdfExecution`, which is what we
2020
/// store in memory for logs.
21-
#[derive(Debug, Clone)]
21+
#[derive(Clone)]
22+
#[cfg_attr(any(test, feature = "testing"), derive(Debug))]
2223
pub enum FunctionOutcome {
2324
Query(UdfOutcome),
2425
Mutation(UdfOutcome),

crates/isolate/src/environment/helpers/validation.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,15 +330,12 @@ impl ValidatedPathAndArgs {
330330

331331
#[cfg(any(test, feature = "testing"))]
332332
pub fn new_for_tests(
333-
udf_path: sync_types::CanonicalizedUdfPath,
333+
path: CanonicalizedComponentFunctionPath,
334334
args: ConvexArray,
335335
npm_version: Option<Version>,
336336
) -> Self {
337337
Self {
338-
path: CanonicalizedComponentFunctionPath {
339-
component: ComponentId::Root,
340-
udf_path,
341-
},
338+
path,
342339
args,
343340
npm_version,
344341
}

crates/isolate/src/environment/udf/outcome.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@ impl UdfOutcome {
252252

253253
#[cfg(test)]
254254
mod tests {
255+
use common::components::{
256+
CanonicalizedComponentFunctionPath,
257+
ComponentId,
258+
};
255259
use proptest::prelude::*;
256260

257261
use super::{
@@ -273,7 +277,10 @@ mod tests {
273277
let version = udf_outcome.udf_server_version.clone();
274278
let identity = udf_outcome_clone.identity.clone();
275279
let path_and_args = ValidatedPathAndArgs::new_for_tests(
276-
udf_path,
280+
CanonicalizedComponentFunctionPath {
281+
component: ComponentId::Root,
282+
udf_path,
283+
},
277284
arguments,
278285
version
279286
);

crates/isolate/src/test_helpers.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use common::{
1717
IndexMetadata,
1818
},
1919
components::{
20+
CanonicalizedComponentFunctionPath,
2021
CanonicalizedComponentModulePath,
2122
ComponentFunctionPath,
2223
ComponentId,
@@ -710,7 +711,10 @@ impl<RT: Runtime, P: Persistence + Clone> UdfTest<RT, P> {
710711

711712
let path: UdfPath = udf_path.parse()?;
712713
let path_and_args = ValidatedPathAndArgs::new_for_tests(
713-
path.canonicalize(),
714+
CanonicalizedComponentFunctionPath {
715+
component: ComponentId::Root,
716+
udf_path: path.canonicalize(),
717+
},
714718
ConvexArray::try_from(vec![ConvexValue::Object(args)])?,
715719
Some(npm_version),
716720
);
@@ -1032,7 +1036,7 @@ impl<RT: Runtime, P: Persistence + Clone> UdfTest<RT, P> {
10321036
identity.into(),
10331037
self.rt.clone(),
10341038
None,
1035-
)?,
1039+
),
10361040
vec![].into(),
10371041
))
10381042
},
@@ -1325,7 +1329,10 @@ pub async fn bogus_udf_request<RT: Runtime>(
13251329
// let (sender, _rx) = oneshot::channel();
13261330
let request = UdfRequest {
13271331
path_and_args: ValidatedPathAndArgs::new_for_tests(
1328-
"path.js:default".parse()?,
1332+
CanonicalizedComponentFunctionPath {
1333+
component: ComponentId::Root,
1334+
udf_path: "path.js:default".parse()?,
1335+
},
13291336
ConvexArray::empty(),
13301337
None,
13311338
),

0 commit comments

Comments
 (0)