Skip to content
This repository was archived by the owner on Feb 6, 2026. It is now read-only.

Commit 423189f

Browse files
committed
feat(dal, sdf): Getting all the functions associated with a schema variant
1 parent 8b56830 commit 423189f

7 files changed

Lines changed: 186 additions & 83 deletions

File tree

lib/dal/src/func.rs

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use si_events::ContentHash;
44
use std::collections::HashMap;
55
use std::string::FromUtf8Error;
66
use std::sync::Arc;
7-
use strum::IntoEnumIterator;
7+
use strum::{AsRefStr, Display, IntoEnumIterator};
88
use telemetry::prelude::*;
99
use thiserror::Error;
1010
use ulid::Ulid;
@@ -48,6 +48,8 @@ pub enum FuncError {
4848
Transactions(#[from] TransactionsError),
4949
#[error("could not acquire lock: {0}")]
5050
TryLock(#[from] tokio::sync::TryLockError),
51+
#[error("unable to determine the function type")]
52+
UnknownFunctionType,
5153
#[error("utf8 error: {0}")]
5254
Utf8(#[from] FromUtf8Error),
5355
#[error("workspace snapshot error: {0}")]
@@ -76,6 +78,7 @@ impl From<Func> for FuncContentV1 {
7678
hidden: value.hidden,
7779
builtin: value.builtin,
7880
backend_response_type: value.backend_response_type,
81+
backend_kind: value.backend_kind,
7982
handler: value.handler,
8083
code_base64: value.code_base64,
8184
code_blake3: value.code_blake3,
@@ -96,6 +99,22 @@ pub fn is_intrinsic(name: &str) -> bool {
9699

97100
pk!(FuncId);
98101

102+
/// Describes what kind of [`Func`] this is.
103+
#[remain::sorted]
104+
#[derive(AsRefStr, Deserialize, Display, Serialize, Debug, Eq, PartialEq, Clone, Copy, Hash)]
105+
#[serde(rename_all = "camelCase")]
106+
#[strum(serialize_all = "camelCase")]
107+
pub enum FuncKind {
108+
Action,
109+
Attribute,
110+
Authentication,
111+
CodeGeneration,
112+
Intrinsic,
113+
Qualification,
114+
SchemaVariantDefinition,
115+
Unknown,
116+
}
117+
99118
/// A `Func` is the declaration of the existence of a function. It has a name,
100119
/// and corresponds to a given function backend (and its associated return types).
101120
///
@@ -132,7 +151,7 @@ impl Func {
132151
link: content.link,
133152
hidden: content.hidden,
134153
builtin: content.builtin,
135-
backend_kind: node_weight.backend_kind(),
154+
backend_kind: content.backend_kind,
136155
backend_response_type: content.backend_response_type,
137156
handler: content.handler,
138157
code_base64: content.code_base64,
@@ -143,7 +162,7 @@ impl Func {
143162
#[allow(clippy::too_many_arguments)]
144163
pub async fn new(
145164
ctx: &DalContext,
146-
name: impl Into<String>,
165+
name: impl Into<String> + Clone,
147166
display_name: Option<impl Into<String>>,
148167
description: Option<impl Into<String>>,
149168
link: Option<impl Into<String>>,
@@ -169,6 +188,7 @@ impl Func {
169188
hidden,
170189
builtin,
171190
backend_response_type,
191+
backend_kind,
172192
handler: handler.map(Into::into),
173193
code_base64,
174194
code_blake3,
@@ -185,9 +205,14 @@ impl Func {
185205
)
186206
.await?;
187207

208+
let func_kind =
209+
Self::determine_func_kind(name.clone().into(), backend_kind, backend_response_type)
210+
.await?;
211+
188212
let change_set = ctx.change_set_pointer()?;
189213
let id = change_set.generate_ulid()?;
190-
let node_weight = NodeWeight::new_func(change_set, id, name.into(), backend_kind, hash)?;
214+
let node_weight =
215+
NodeWeight::new_func(change_set, id, name.clone().into(), func_kind, hash)?;
191216

192217
let workspace_snapshot = ctx.workspace_snapshot()?;
193218
workspace_snapshot.add_node(node_weight.clone()).await?;
@@ -208,6 +233,45 @@ impl Func {
208233
Ok(Self::assemble(&func_node_weight, &content))
209234
}
210235

236+
pub async fn determine_func_kind(
237+
func_name: String,
238+
func_backend_kind: FuncBackendKind,
239+
func_backend_response_type: FuncBackendResponseType,
240+
) -> FuncResult<FuncKind> {
241+
match func_backend_kind {
242+
FuncBackendKind::JsAttribute => {
243+
return match func_backend_response_type {
244+
FuncBackendResponseType::CodeGeneration => Ok(FuncKind::CodeGeneration),
245+
FuncBackendResponseType::Qualification => Ok(FuncKind::Qualification),
246+
FuncBackendResponseType::SchemaVariantDefinition => {
247+
dbg!("THIS IS FUCKED!");
248+
Ok(FuncKind::SchemaVariantDefinition)
249+
}
250+
_ => Ok(FuncKind::Attribute),
251+
}
252+
}
253+
FuncBackendKind::JsAction => return Ok(FuncKind::Action),
254+
FuncBackendKind::JsAuthentication => return Ok(FuncKind::Authentication),
255+
FuncBackendKind::JsSchemaVariantDefinition => {
256+
return Ok(FuncKind::SchemaVariantDefinition)
257+
}
258+
FuncBackendKind::Array
259+
| FuncBackendKind::Boolean
260+
| FuncBackendKind::Diff
261+
| FuncBackendKind::Identity
262+
| FuncBackendKind::Integer
263+
| FuncBackendKind::Map
264+
| FuncBackendKind::Object
265+
| FuncBackendKind::String
266+
| FuncBackendKind::Unset
267+
| FuncBackendKind::Validation => return Ok(FuncKind::Intrinsic),
268+
_ => {
269+
dbg!(&func_name, &func_backend_kind, &func_backend_response_type);
270+
Err(FuncError::UnknownFunctionType)
271+
}
272+
}
273+
}
274+
211275
pub fn metadata_view(&self) -> FuncMetadataView {
212276
FuncMetadataView {
213277
display_name: self
@@ -334,17 +398,13 @@ impl Func {
334398

335399
let workspace_snapshot = ctx.workspace_snapshot()?;
336400

337-
// If both either the name or backend_kind have changed, *and* parts of the FuncContent
401+
// If the name HAS changed, *and* parts of the FuncContent
338402
// have changed, this ends up updating the node for the function twice. This could be
339403
// optimized to do it only once.
340-
if func.name.as_str() != node_weight.name()
341-
|| func.backend_kind != node_weight.backend_kind()
342-
{
404+
if func.name.as_str() != node_weight.name() {
343405
let original_node_index = workspace_snapshot.get_node_index_by_id(func.id).await?;
344406

345-
node_weight
346-
.set_name(func.name.as_str())
347-
.set_backend_kind(func.backend_kind);
407+
node_weight.set_name(func.name.as_str());
348408

349409
workspace_snapshot
350410
.add_node(NodeWeight::Func(

lib/dal/src/layer_db_types/content_types.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use crate::{
77
func::argument::FuncArgumentKind, key_pair::KeyPairPk, prop::WidgetOptions,
88
property_editor::schema::WidgetKind, secret::SecretPk,
99
socket::connection_annotation::ConnectionAnnotation, ActionCompletionStatus, ActionKind,
10-
ActionPrototypeId, ComponentId, ComponentType, FuncBackendResponseType, FuncId, PropId,
11-
PropKind, SocketArity, SocketKind, Timestamp, UserPk,
10+
ActionPrototypeId, ComponentId, ComponentType, FuncBackendKind, FuncBackendResponseType,
11+
FuncId, PropId, PropKind, SocketArity, SocketKind, Timestamp, UserPk,
1212
};
1313

1414
/// This type gathers up all the kinds of things we will store in the
@@ -219,6 +219,7 @@ pub struct FuncContentV1 {
219219
pub hidden: bool,
220220
pub builtin: bool,
221221
pub backend_response_type: FuncBackendResponseType,
222+
pub backend_kind: FuncBackendKind,
222223
pub handler: Option<String>,
223224
pub code_base64: Option<String>,
224225
/// A hash of the code above

lib/dal/src/schema/variant.rs

Lines changed: 78 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! This module contains [`SchemaVariant`](crate::SchemaVariant), which is t/he "class" of a
22
//! [`Component`](crate::Component).
33
4-
use petgraph::{Direction, Incoming};
4+
use petgraph::{Direction, Incoming, Outgoing};
55
use serde::{Deserialize, Serialize};
66
use serde_json::Value;
77
use si_events::ContentHash;
@@ -20,7 +20,7 @@ use crate::attribute::prototype::AttributePrototypeError;
2020
use crate::change_set_pointer::ChangeSetPointerError;
2121
use crate::func::argument::{FuncArgument, FuncArgumentError};
2222
use crate::func::intrinsics::IntrinsicFunc;
23-
use crate::func::FuncError;
23+
use crate::func::{FuncError, FuncKind};
2424
use crate::layer_db_types::{
2525
InputSocketContent, OutputSocketContent, SchemaVariantContent,
2626
SchemaVariantContentDiscriminants, SchemaVariantContentV1,
@@ -41,16 +41,14 @@ use crate::workspace_snapshot::WorkspaceSnapshotError;
4141
use crate::{
4242
pk,
4343
schema::variant::leaves::{LeafInput, LeafInputLocation, LeafKind},
44-
AttributePrototype, AttributePrototypeId, ComponentId, ComponentType, DalContext, Func,
45-
FuncBackendKind, FuncId, InputSocket, OutputSocket, OutputSocketId, Prop, PropId, PropKind,
46-
Schema, SchemaError, SchemaId, SocketArity, Timestamp, TransactionsError,
44+
ActionPrototype, ActionPrototypeError, AttributePrototype, AttributePrototypeId, ComponentId,
45+
ComponentType, DalContext, Func, FuncId, InputSocket, OutputSocket, OutputSocketId, Prop,
46+
PropId, PropKind, Schema, SchemaError, SchemaId, SocketArity, Timestamp, TransactionsError,
4747
};
4848
use crate::{FuncBackendResponseType, InputSocketId};
4949

5050
use self::root_prop::RootPropChild;
5151

52-
// use self::leaves::{LeafInput, LeafInputLocation, LeafKind};
53-
5452
pub mod definition;
5553
pub mod leaves;
5654
pub mod root_prop;
@@ -64,6 +62,8 @@ pub const SCHEMA_VARIANT_VERSION: SchemaVariantContentDiscriminants =
6462
#[remain::sorted]
6563
#[derive(Error, Debug)]
6664
pub enum SchemaVariantError {
65+
#[error("action prototype error: {0}")]
66+
ActionPrototype(String),
6767
#[error("attribute prototype error: {0}")]
6868
AttributePrototype(#[from] AttributePrototypeError),
6969
#[error("attribute argument prototype error: {0}")]
@@ -305,7 +305,7 @@ impl SchemaVariant {
305305
.await?;
306306

307307
let func_node_weight = node_weight.get_func_node_weight()?;
308-
if func_node_weight.backend_kind() == FuncBackendKind::JsSchemaVariantDefinition {
308+
if func_node_weight.func_kind() == FuncKind::SchemaVariantDefinition {
309309
return Ok(Some(func_node_weight.id().into()));
310310
}
311311
}
@@ -1040,39 +1040,81 @@ impl SchemaVariant {
10401040
ctx: &DalContext,
10411041
schema_variant_id: SchemaVariantId,
10421042
) -> SchemaVariantResult<Vec<Func>> {
1043+
let workspace_snapshot = ctx.workspace_snapshot()?;
10431044
let mut all_funcs = vec![];
1044-
// auth funcs
1045-
for func_id in Self::list_auth_func_ids_for_schema_variant(ctx, schema_variant_id).await? {
1046-
let func = Func::get_by_id(ctx, func_id).await?;
1047-
all_funcs.push(func);
1048-
}
1049-
// attribute funcs
1050-
for func_id in
1051-
Self::list_attribute_func_ids_for_schema_variant(ctx, schema_variant_id).await?
1052-
{
1053-
let func = Func::get_by_id(ctx, func_id).await?;
1054-
all_funcs.push(func);
1055-
}
1056-
// qualification funcs
1057-
for func_id in
1058-
Self::list_qualification_func_ids_for_schema_variant(ctx, schema_variant_id).await?
1059-
{
1060-
let func = Func::get_by_id(ctx, func_id).await?;
1061-
all_funcs.push(func);
1045+
1046+
let sv = Self::get_by_id(ctx, schema_variant_id).await?;
1047+
1048+
let prop_list = sv.dump_props_as_list(ctx).await?;
1049+
for prop_path in prop_list {
1050+
let prop_id = Prop::find_prop_id_by_path(ctx, schema_variant_id, &prop_path).await?;
1051+
// Let's get the Attribute funcs now
1052+
if let Some(ap_id) = AttributePrototype::find_for_prop(ctx, prop_id, &None).await? {
1053+
let func_id = AttributePrototype::func_id(ctx, ap_id).await?;
1054+
1055+
let node_weight = workspace_snapshot
1056+
.get_node_weight_by_id(func_id)
1057+
.await?
1058+
.get_func_node_weight()?;
1059+
1060+
match node_weight.func_kind() {
1061+
FuncKind::Attribute => {
1062+
let func = Func::get_by_id(ctx, func_id).await?;
1063+
all_funcs.push(func);
1064+
}
1065+
1066+
_ => {}
1067+
}
1068+
}
1069+
1070+
// Now let's get all of the outgoing edges for the Prop
1071+
for (edge_weight, _source, _target) in
1072+
workspace_snapshot.edges_directed(prop_id, Outgoing).await?
1073+
{
1074+
if let EdgeWeightKind::Prototype(Some(key)) = edge_weight.kind() {
1075+
if let Some(func_id) = Func::find_by_name(ctx, key).await? {
1076+
let func = Func::get_by_id(ctx, func_id).await?;
1077+
all_funcs.push(func);
1078+
}
1079+
}
1080+
}
10621081
}
1063-
// action funcs
1064-
for func_id in Self::list_action_func_ids_for_schema_variant(ctx, schema_variant_id).await?
1065-
{
1066-
let func = Func::get_by_id(ctx, func_id).await?;
1067-
all_funcs.push(func);
1082+
1083+
// Let's get all of the Authentication funcs
1084+
let auth_func_ids =
1085+
Self::list_auth_func_ids_for_schema_variant(ctx, schema_variant_id).await?;
1086+
for auth_func_id in auth_func_ids {
1087+
let auth_func = Func::get_by_id(ctx, auth_func_id).await?;
1088+
// We may not need this - the list_auth_func_ids_for_schema_variant returns multiple
1089+
// of the same type
1090+
if !all_funcs.contains(&auth_func) {
1091+
all_funcs.push(auth_func);
1092+
}
10681093
}
1069-
//code gen
1070-
for func_id in
1071-
Self::list_code_gen_func_ids_for_schema_variant(ctx, schema_variant_id).await?
1072-
{
1073-
let func = Func::get_by_id(ctx, func_id).await?;
1094+
1095+
let action_prototype_nodes = workspace_snapshot
1096+
.outgoing_targets_for_edge_weight_kind(
1097+
schema_variant_id,
1098+
EdgeWeightKindDiscriminants::ActionPrototype,
1099+
)
1100+
.await?;
1101+
for action_prototype_node in action_prototype_nodes {
1102+
let weight = workspace_snapshot
1103+
.get_node_weight(action_prototype_node)
1104+
.await?;
1105+
let ap = ActionPrototype::get_by_id(ctx, weight.id().into())
1106+
.await
1107+
.map_err(|e| SchemaVariantError::ActionPrototype(e.to_string()))?;
1108+
let func = Func::get_by_id(
1109+
ctx,
1110+
ap.func_id(ctx)
1111+
.await
1112+
.map_err(|e| SchemaVariantError::ActionPrototype(e.to_string()))?,
1113+
)
1114+
.await?;
10741115
all_funcs.push(func);
10751116
}
1117+
10761118
Ok(all_funcs)
10771119
}
10781120

lib/dal/src/workspace_snapshot/graph/tests/rebase.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ mod test {
55
use si_events::ContentHash;
66

77
use crate::change_set_pointer::ChangeSetPointer;
8+
use crate::func::FuncKind;
89
use crate::workspace_snapshot::content_address::ContentAddress;
910
use crate::workspace_snapshot::edge_weight::{EdgeWeight, EdgeWeightKind};
1011
use crate::workspace_snapshot::node_weight::category_node_weight::CategoryNodeKind;
1112
use crate::workspace_snapshot::node_weight::NodeWeight;
1213
use crate::workspace_snapshot::node_weight::{ContentNodeWeight, FuncNodeWeight};
13-
use crate::FuncBackendKind;
1414
use crate::WorkspaceSnapshotGraph;
1515

1616
#[test]
@@ -59,7 +59,7 @@ mod test {
5959
func_id,
6060
ContentAddress::Func(ContentHash::from("foo")),
6161
"foo".to_string(),
62-
FuncBackendKind::String,
62+
FuncKind::Intrinsic,
6363
)
6464
.expect("could not create func node weight");
6565
let func_node_index = onto

lib/dal/src/workspace_snapshot/node_weight.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use ulid::Ulid;
77

88
use crate::func::execution::FuncExecutionPk;
99
use crate::workspace_snapshot::vector_clock::VectorClockId;
10-
use crate::FuncBackendKind;
1110
use crate::{
1211
change_set_pointer::{ChangeSetPointer, ChangeSetPointerError},
1312
workspace_snapshot::{
@@ -17,6 +16,7 @@ use crate::{
1716
PropKind,
1817
};
1918

19+
use crate::func::FuncKind;
2020
pub use attribute_prototype_argument_node_weight::ArgumentTargets;
2121
pub use attribute_prototype_argument_node_weight::AttributePrototypeArgumentNodeWeight;
2222
pub use attribute_value_node_weight::AttributeValueNodeWeight;
@@ -576,15 +576,15 @@ impl NodeWeight {
576576
change_set: &ChangeSetPointer,
577577
func_id: Ulid,
578578
name: impl AsRef<str>,
579-
backend_kind: FuncBackendKind,
579+
func_kind: FuncKind,
580580
content_hash: ContentHash,
581581
) -> NodeWeightResult<Self> {
582582
Ok(NodeWeight::Func(FuncNodeWeight::new(
583583
change_set,
584584
func_id,
585585
ContentAddress::Func(content_hash),
586586
name.as_ref().to_string(),
587-
backend_kind,
587+
func_kind,
588588
)?))
589589
}
590590

0 commit comments

Comments
 (0)