Skip to content

Commit

Permalink
Merge pull request #4114 from systeminit/brit/bug-450-fix-reactivity-…
Browse files Browse the repository at this point in the history
…return-correct-variants

Fire WS Events when bindings change, funcs are unlocked, and unlocking funcs creates new unlocked variants
  • Loading branch information
britmyerss committed Jul 8, 2024
2 parents 4804504 + a891ead commit de7a00c
Show file tree
Hide file tree
Showing 23 changed files with 312 additions and 208 deletions.
28 changes: 21 additions & 7 deletions lib/dal/src/func.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use argument::{FuncArgument, FuncArgumentError};
use authoring::FuncAuthoringError;
use authoring::{FuncAuthoringClient, FuncAuthoringError};
use base64::{engine::general_purpose, Engine};
use binding::{FuncBinding, FuncBindingError};
use itertools::Itertools;
Expand Down Expand Up @@ -740,6 +740,7 @@ impl Func {
.into_iter()
.map(Into::into)
.collect_vec();
let types = Self::get_types(ctx, self.id).await?;
Ok(FuncSummary {
func_id: self.id.into(),
kind: self.kind.into(),
Expand All @@ -749,8 +750,26 @@ impl Func {
is_locked: self.is_locked,
arguments,
bindings: si_frontend_types::FuncBindings { bindings },
types: Some(types),
})
}
// helper to get updated types to fire WSEvents so SDF can decide when these events need to fire
pub async fn get_types(ctx: &DalContext, func_id: FuncId) -> FuncResult<String> {
let func = Func::get_by_id_or_error(ctx, func_id).await?;
let types = [
FuncAuthoringClient::compile_return_types(
func.backend_response_type,
func.backend_kind,
),
FuncAuthoringClient::compile_types_from_bindings(ctx, func_id)
.await
.map_err(Box::new)?
.as_str(),
FuncAuthoringClient::compile_langjs_types(),
]
.join("\n");
Ok(types)
}
}

#[derive(Clone, Deserialize, Serialize, Debug, Eq, PartialEq)]
Expand All @@ -764,7 +783,6 @@ pub struct FuncWsEventPayload {
pub struct FuncWsEventFuncSummary {
change_set_id: ChangeSetId,
func_summary: si_frontend_types::FuncSummary,
types: String,
}
#[derive(Clone, Deserialize, Serialize, Debug, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -810,14 +828,12 @@ impl WsEvent {
pub async fn func_updated(
ctx: &DalContext,
func_summary: si_frontend_types::FuncSummary,
types: String,
) -> WsEventResult<Self> {
WsEvent::new(
ctx,
WsPayload::FuncUpdated(FuncWsEventFuncSummary {
change_set_id: ctx.change_set_id(),
func_summary,
types,
}),
)
.await
Expand All @@ -826,14 +842,12 @@ impl WsEvent {
pub async fn func_created(
ctx: &DalContext,
func_summary: si_frontend_types::FuncSummary,
types: String,
) -> WsEventResult<Self> {
WsEvent::new(
ctx,
WsPayload::FuncUpdated(FuncWsEventFuncSummary {
WsPayload::FuncCreated(FuncWsEventFuncSummary {
change_set_id: ctx.change_set_id(),
func_summary,
types,
}),
)
.await
Expand Down
95 changes: 22 additions & 73 deletions lib/dal/src/func/authoring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -619,8 +619,12 @@ impl FuncAuthoringClient {
binding.port_binding_to_new_func(ctx, new_func.id).await?;
}
}
// ws event

let variant = SchemaVariant::get_by_id_or_error(ctx, schema_variant_id).await?;
WsEvent::schema_variant_updated(ctx, schema, variant)
.await?
.publish_on_commit(ctx)
.await?;
new_func
} else if current_schema_variant.is_default(ctx).await? {
let new_schema_variant =
Expand All @@ -629,10 +633,6 @@ impl FuncAuthoringClient {
.map_err(Box::new)?;
let new_schema_variant_id = new_schema_variant.id();

WsEvent::schema_variant_created(ctx, schema, new_schema_variant)
.await?
.publish_on_commit(ctx)
.await?;
let unlocked_latest =
FuncBinding::get_bindings_for_unlocked_schema_variants(ctx, func_id).await?;

Expand All @@ -645,6 +645,11 @@ impl FuncAuthoringClient {
binding.port_binding_to_new_func(ctx, new_func.id).await?;
}
}
let new_variant = SchemaVariant::get_by_id_or_error(ctx, new_schema_variant_id).await?;
WsEvent::schema_variant_created(ctx, schema, new_variant)
.await?
.publish_on_commit(ctx)
.await?;

new_func
} else {
Expand All @@ -653,37 +658,6 @@ impl FuncAuthoringClient {
));
};

let bindings: Vec<si_frontend_types::FuncBinding> = FuncBinding::for_func_id(ctx, func_id)
.await?
.into_iter()
.map(|binding| binding.into())
.collect();
let new_bindings: Vec<si_frontend_types::FuncBinding> =
FuncBinding::for_func_id(ctx, new_func.id)
.await?
.into_iter()
.map(|binding| binding.into())
.collect();
WsEvent::func_bindings_updated(
ctx,
si_frontend_types::FuncBindings { bindings },
Self::compile_types_from_bindings(ctx, func_id).await?,
)
.await?
.publish_on_commit(ctx)
.await?;

WsEvent::func_bindings_updated(
ctx,
si_frontend_types::FuncBindings {
bindings: new_bindings,
},
Self::compile_types_from_bindings(ctx, new_func.id).await?,
)
.await?
.publish_on_commit(ctx)
.await?;

Ok(new_func)
}

Expand All @@ -697,7 +671,7 @@ impl FuncAuthoringClient {
func_id: FuncId,
) -> FuncAuthoringResult<Func> {
let old_func = Func::get_by_id_or_error(ctx, func_id).await?;

let mut new_schema_variants = vec![];
// Create unlocked versions of all schema variants that are locked, default and have a bindings to old func
for (schema_variant_id, _) in
FuncBinding::get_bindings_for_default_and_unlocked_schema_variants(ctx, old_func.id)
Expand All @@ -706,20 +680,14 @@ impl FuncAuthoringClient {
// todo figure out ws event here
// See if the Schema Variant is locked
if SchemaVariant::is_locked_by_id(ctx, schema_variant_id).await? {
let schema_id =
SchemaVariant::schema_id_for_schema_variant_id(ctx, schema_variant_id).await?;
dbg!("creating unlocked copy");
// if it's locked, create an unlocked copy of it
// creating the unlocked copy will keep the func in question bound at the same place (so we'll see another binding for the
// func after creating a copy)
let new_schema_variant =
VariantAuthoringClient::create_unlocked_variant_copy(ctx, schema_variant_id)
.await
.map_err(Box::new)?;
WsEvent::schema_variant_created(ctx, schema_id, new_schema_variant)
.await?
.publish_on_commit(ctx)
.await?;
new_schema_variants.push(new_schema_variant);
}
}

Expand All @@ -735,37 +703,18 @@ impl FuncAuthoringClient {
// for the binding, remove it and create the equivalent for the new one
binding.port_binding_to_new_func(ctx, new_func.id).await?;
}
// get latest bindings and fire an event
let bindings: Vec<si_frontend_types::FuncBinding> = FuncBinding::for_func_id(ctx, func_id)
// now fire the event with all the new schema variants that have updated bindings with the new func
for schema_variant in new_schema_variants {
WsEvent::schema_variant_created(
ctx,
schema_variant.schema(ctx).await?.id(),
schema_variant,
)
.await?
.into_iter()
.map(|binding| binding.into())
.collect();
let new_bindings: Vec<si_frontend_types::FuncBinding> =
FuncBinding::for_func_id(ctx, new_func.id)
.await?
.into_iter()
.map(|binding| binding.into())
.collect();
WsEvent::func_bindings_updated(
ctx,
si_frontend_types::FuncBindings { bindings },
Self::compile_types_from_bindings(ctx, func_id).await?,
)
.await?
.publish_on_commit(ctx)
.await?;
.publish_on_commit(ctx)
.await?;
}

WsEvent::func_bindings_updated(
ctx,
si_frontend_types::FuncBindings {
bindings: new_bindings,
},
Self::compile_types_from_bindings(ctx, new_func.id).await?,
)
.await?
.publish_on_commit(ctx)
.await?;
Ok(new_func)
}

Expand Down
30 changes: 1 addition & 29 deletions lib/dal/src/func/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ use crate::{
FuncError, FuncId, PropId, SchemaVariantError, SchemaVariantId,
};
use crate::{
ChangeSetId, ComponentId, OutputSocketId, SchemaId, SchemaVariant, WorkspaceSnapshotError,
WsEvent, WsEventError, WsEventResult, WsPayload,
ComponentId, OutputSocketId, SchemaId, SchemaVariant, WorkspaceSnapshotError, WsEventError,
};
pub use attribute_argument::AttributeArgumentBinding;
pub use attribute_argument::AttributeFuncArgumentSource;
Expand Down Expand Up @@ -646,30 +645,3 @@ impl FuncBinding {
Ok(auth_bindings)
}
}

#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct FuncBindingsWsEventPayload {
change_set_id: ChangeSetId,
#[serde(flatten)]
bindings: si_frontend_types::FuncBindings,
types: String,
}

impl WsEvent {
pub async fn func_bindings_updated(
ctx: &DalContext,
bindings: si_frontend_types::FuncBindings,
types: String,
) -> WsEventResult<Self> {
WsEvent::new(
ctx,
WsPayload::FuncBindingsUpdated(FuncBindingsWsEventPayload {
change_set_id: ctx.change_set_id(),
bindings,
types,
}),
)
.await
}
}
8 changes: 3 additions & 5 deletions lib/dal/src/func/binding/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
SchemaVariantId,
};

use super::{FuncBinding, FuncBindingResult};
use super::{EventualParent, FuncBinding, FuncBindingResult};

#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq, Hash)]
pub struct ActionBinding {
Expand Down Expand Up @@ -124,17 +124,15 @@ impl ActionBinding {
pub async fn delete_action_binding(
ctx: &DalContext,
action_prototype_id: ActionPrototypeId,
) -> FuncBindingResult<Vec<FuncBinding>> {
) -> FuncBindingResult<EventualParent> {
// don't delete binding if parent is locked
let schema_variant_id =
ActionPrototype::schema_variant_id(ctx, action_prototype_id).await?;
SchemaVariant::error_if_locked(ctx, schema_variant_id).await?;

let func_id = ActionPrototype::func_id(ctx, action_prototype_id).await?;

ActionPrototype::remove(ctx, action_prototype_id).await?;

FuncBinding::for_func_id(ctx, func_id).await
Ok(EventualParent::SchemaVariant(schema_variant_id))
}

pub(crate) async fn compile_action_types(
Expand Down
10 changes: 4 additions & 6 deletions lib/dal/src/func/binding/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ impl AttributeBinding {
eventual_parent: Option<EventualParent>,
output_location: AttributeFuncDestination,
prototype_arguments: Vec<AttributeArgumentBinding>,
) -> FuncBindingResult<Vec<FuncBinding>> {
) -> FuncBindingResult<AttributePrototype> {
let func = Func::get_by_id_or_error(ctx, func_id).await?;
if func.kind != FuncKind::Attribute {
return Err(FuncBindingError::UnexpectedFuncKind(func.kind));
Expand Down Expand Up @@ -327,7 +327,7 @@ impl AttributeBinding {
}
};
}
FuncBinding::for_func_id(ctx, func_id).await
Ok(attribute_prototype)
}

#[instrument(
Expand Down Expand Up @@ -437,13 +437,11 @@ impl AttributeBinding {
pub async fn reset_attribute_binding(
ctx: &DalContext,
attribute_prototype_id: AttributePrototypeId,
) -> FuncBindingResult<Vec<FuncBinding>> {
) -> FuncBindingResult<EventualParent> {
// don't update binding args if the parent is locked
let eventual_parent = Self::find_eventual_parent(ctx, attribute_prototype_id).await?;
eventual_parent.error_if_locked(ctx).await?;

let func_id = AttributePrototype::func_id(ctx, attribute_prototype_id).await?;

if let Some(attribute_value_id) =
AttributePrototype::attribute_value_id(ctx, attribute_prototype_id).await?
{
Expand All @@ -465,7 +463,7 @@ impl AttributeBinding {
AttributePrototypeArgument::remove(ctx, apa).await?;
}
}
FuncBinding::for_func_id(ctx, func_id).await
Ok(eventual_parent)
}

pub(crate) async fn compile_attribute_types(
Expand Down
6 changes: 3 additions & 3 deletions lib/dal/src/func/binding/authentication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use telemetry::prelude::*;

use crate::{DalContext, FuncId, SchemaVariant, SchemaVariantId};

use super::{FuncBinding, FuncBindingResult};
use super::{EventualParent, FuncBinding, FuncBindingResult};

#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq, Hash)]
pub struct AuthBinding {
Expand Down Expand Up @@ -56,11 +56,11 @@ impl AuthBinding {
ctx: &DalContext,
func_id: FuncId,
schema_variant_id: SchemaVariantId,
) -> FuncBindingResult<Vec<FuncBinding>> {
) -> FuncBindingResult<EventualParent> {
// don't delete binding if parent is locked
SchemaVariant::error_if_locked(ctx, schema_variant_id).await?;
SchemaVariant::remove_authentication_prototype(ctx, func_id, schema_variant_id).await?;
FuncBinding::for_func_id(ctx, func_id).await
Ok(EventualParent::SchemaVariant(schema_variant_id))
}

pub(crate) async fn port_binding_to_new_func(
Expand Down
7 changes: 2 additions & 5 deletions lib/dal/src/func/binding/leaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,12 @@ impl LeafBinding {
pub async fn delete_leaf_func_binding(
ctx: &DalContext,
attribute_prototype_id: AttributePrototypeId,
) -> FuncBindingResult<Vec<FuncBinding>> {
) -> FuncBindingResult<EventualParent> {
// don't delete binding if parent is locked
let eventual_parent =
AttributeBinding::find_eventual_parent(ctx, attribute_prototype_id).await?;
eventual_parent.error_if_locked(ctx).await?;

let func_id = AttributePrototype::func_id(ctx, attribute_prototype_id).await?;

// Delete all attribute prototype arguments for the given prototype.
for attribute_prototype_argument_id in
AttributePrototypeArgument::list_ids_for_prototype(ctx, attribute_prototype_id).await?
Expand All @@ -242,8 +240,7 @@ impl LeafBinding {
}
AttributePrototype::remove(ctx, attribute_prototype_id).await?;

// Return the updated bindings.
FuncBinding::for_func_id(ctx, func_id).await
Ok(eventual_parent)
}

pub(crate) async fn compile_leaf_func_types(
Expand Down
Loading

0 comments on commit de7a00c

Please sign in to comment.