Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NU-1847] Definition service with the ability to return definition without config from additional provider #7021

Merged
merged 25 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
81ceb56
Definition service with the ability to return definition without conf…
mateuszkp96 Oct 15, 2024
7bf1751
Changelog
mateuszkp96 Oct 15, 2024
32aa327
Tests fixes
mateuszkp96 Oct 16, 2024
65cb11d
Test fix
mateuszkp96 Oct 16, 2024
d89e7bf
Merge branch 'staging' into definitions-service-raw-parameters-support
mateuszkp96 Oct 23, 2024
8a32c77
Review fixes
mateuszkp96 Oct 25, 2024
06bf60d
Merge branch 'staging' into definitions-service-raw-parameters-support
mateuszkp96 Oct 25, 2024
c551dc4
WIP
mateuszkp96 Oct 27, 2024
3d5ab08
Merge branch 'staging' into definitions-service-raw-parameters-support
mateuszkp96 Oct 27, 2024
fb80b7d
Fixes
mateuszkp96 Oct 27, 2024
996f5af
Fixes
mateuszkp96 Oct 28, 2024
266619b
Merge branch 'staging' into definitions-service-raw-parameters-support
mateuszkp96 Oct 28, 2024
fb71d55
Fixes
mateuszkp96 Oct 28, 2024
dd5f13e
Fixes
mateuszkp96 Oct 28, 2024
10bd125
Merge branch 'staging' into definitions-service-raw-parameters-support
mateuszkp96 Oct 28, 2024
b086a21
Fixes
mateuszkp96 Oct 28, 2024
abe3515
Merge branch 'staging' into definitions-service-raw-parameters-support
mateuszkp96 Oct 28, 2024
b0652f9
Merge branch 'staging' into definitions-service-raw-parameters-support
mateuszkp96 Oct 28, 2024
cd38bee
Review fixes
mateuszkp96 Oct 28, 2024
b393946
Review fixes
mateuszkp96 Oct 28, 2024
ab19b9b
Tests fixes
mateuszkp96 Oct 28, 2024
ff8c49f
Review fixes
mateuszkp96 Oct 28, 2024
3d76cbd
Merge branch 'staging' into definitions-service-raw-parameters-support
mateuszkp96 Oct 28, 2024
14f6fb7
Fixes
mateuszkp96 Oct 29, 2024
170f232
Merge branch 'staging' into definitions-service-raw-parameters-support
mateuszkp96 Oct 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import pl.touk.nussknacker.engine.api.process._
import pl.touk.nussknacker.engine.canonicalgraph.CanonicalProcess
import pl.touk.nussknacker.engine.compile.ProcessCompilerData
import pl.touk.nussknacker.engine.compiledgraph.part.ProcessPart
import pl.touk.nussknacker.engine.definition.component.ComponentDefinitionWithImplementation
import pl.touk.nussknacker.engine.definition.component.Components.ComponentDefinitionExtractionMode
import pl.touk.nussknacker.engine.definition.component.{ComponentDefinitionWithImplementation, Components}
import pl.touk.nussknacker.engine.definition.model.{ModelDefinition, ModelDefinitionWithClasses}
import pl.touk.nussknacker.engine.dict.SimpleDictRegistry
import pl.touk.nussknacker.engine.modelconfig.ComponentsUiConfig
Expand Down Expand Up @@ -52,8 +53,14 @@ class InterpreterSetup[T: ClassTag] {
) ::: additionalComponents

val definitions = ModelDefinition(
ComponentDefinitionWithImplementation
.forList(components, ComponentsUiConfig.Empty, id => DesignerWideComponentId(id.toString), Map.empty),
Components
.forList(
components,
ComponentsUiConfig.Empty,
id => DesignerWideComponentId(id.toString),
Map.empty,
ComponentDefinitionExtractionMode.FinalDefinition
),
ModelDefinitionBuilder.emptyExpressionConfig,
ClassExtractionSettings.Default
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ package object definition {
// should be invalidated
branchParam: Boolean,
hintText: Option[String],
label: String
label: String,
// This attribute is used only by external project
requiredParam: Boolean,
)

@JsonCodec(encodeOnly = true) final case class UIComponentDefinition(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package pl.touk.nussknacker.ui.api

import akka.http.scaladsl.model._
import akka.http.scaladsl.server.{Directives, Route}
import akka.http.scaladsl.server.{Directive1, Directives, Route}
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import pl.touk.nussknacker.ui.definition.DefinitionsService
import pl.touk.nussknacker.ui.definition.DefinitionsService.ComponentUiConfigMode
import pl.touk.nussknacker.ui.process.processingtype.provider.ProcessingTypeDataProvider
import pl.touk.nussknacker.ui.security.api.LoggedUser
import pl.touk.nussknacker.ui.util.NuPathMatchers
Expand All @@ -25,8 +26,8 @@ class DefinitionResources(
.map { case (definitionsService) =>
pathEndOrSingleSlash {
get {
parameter(Symbol("isFragment").as[Boolean]) { isFragment =>
complete(definitionsService.prepareUIDefinitions(processingType, isFragment))
(isFragmentParam & componentUiConfigModeParam) { (isFragment, componentUiConfigMode) =>
complete(definitionsService.prepareUIDefinitions(processingType, isFragment, componentUiConfigMode))
}
}
}
Expand All @@ -37,4 +38,14 @@ class DefinitionResources(
}
}

private val isFragmentParam: Directive1[Boolean] = parameter(Symbol("isFragment").as[Boolean])

private val componentUiConfigModeParam: Directive1[ComponentUiConfigMode] = {
// parameter used only by an external project to fetch component definitions without enrichments
parameter("enrichedWithUiConfig".as[Boolean].optional).flatMap {
case Some(true) | None => provide(ComponentUiConfigMode.EnrichedWithUiConfig)
case Some(false) => provide(ComponentUiConfigMode.BasicConfig)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import cats.data.Validated.{Invalid, Valid}
import com.typesafe.config.Config
import com.typesafe.scalalogging.LazyLogging
import net.ceedubs.ficus.readers.ValueReader
import pl.touk.nussknacker.engine.definition.component.Components.ComponentDefinitionExtractionMode
import pl.touk.nussknacker.engine.util.config.FicusReaders
import pl.touk.nussknacker.ui.api._
import pl.touk.nussknacker.ui.config.Implicits.parseOptionalConfig
Expand All @@ -27,6 +28,7 @@ final case class FeatureTogglesConfig(
testDataSettings: TestDataSettings,
enableConfigEndpoint: Boolean,
redirectAfterArchive: Boolean,
componentDefinitionExtractionMode: ComponentDefinitionExtractionMode
)

object FeatureTogglesConfig extends LazyLogging {
Expand Down Expand Up @@ -55,6 +57,7 @@ object FeatureTogglesConfig extends LazyLogging {
val intervalTimeSettings = config.as[IntervalTimeSettings]("intervalTimeSettings")
val testDataSettings = config.as[TestDataSettings]("testDataSettings")
val redirectAfterArchive = config.getAs[Boolean]("redirectAfterArchive").getOrElse(true)
val componentDefinitionExtractionMode = parseComponentDefinitionExtractionMode(config)

FeatureTogglesConfig(
development = isDevelopmentMode,
Expand All @@ -72,6 +75,7 @@ object FeatureTogglesConfig extends LazyLogging {
testDataSettings = testDataSettings,
enableConfigEndpoint = enableConfigEndpoint,
redirectAfterArchive = redirectAfterArchive,
componentDefinitionExtractionMode = componentDefinitionExtractionMode,
)
}

Expand All @@ -90,4 +94,13 @@ object FeatureTogglesConfig extends LazyLogging {
}
}

private def parseComponentDefinitionExtractionMode(config: Config): ComponentDefinitionExtractionMode = {
val configPath = "enableBasicDefinitionsForComponents"
if (config.hasPath(configPath) && config.getBoolean(configPath)) {
ComponentDefinitionExtractionMode.FinalAndBasicDefinitions
} else {
ComponentDefinitionExtractionMode.FinalDefinition
}
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package pl.touk.nussknacker.ui.definition

import cats.data.NonEmptySet
import pl.touk.nussknacker.engine.ModelData
import pl.touk.nussknacker.engine.api.component.Component.AllowedProcessingModes
import pl.touk.nussknacker.engine.api.component.{ComponentType, ProcessingMode}
import pl.touk.nussknacker.engine.canonicalgraph.CanonicalProcess
import pl.touk.nussknacker.engine.definition.component.ComponentDefinitionWithImplementation
import pl.touk.nussknacker.engine.definition.component.{ComponentDefinitionWithImplementation, Components}
import pl.touk.nussknacker.engine.definition.component.bultin.BuiltInComponentsDefinitionsPreparer
import pl.touk.nussknacker.engine.definition.fragment.FragmentComponentDefinitionExtractor
import pl.touk.nussknacker.engine.definition.model.ModelDefinition
Expand All @@ -21,7 +19,7 @@ class AlignedComponentsDefinitionProvider(
def getAlignedComponentsWithBuiltInComponentsAndFragments(
forFragment: Boolean,
fragments: List[CanonicalProcess],
): List[ComponentDefinitionWithImplementation] = {
): Components = {
val filteredModel = if (forFragment) {
modelDefinition
.filterComponents(_.componentType != ComponentType.Source)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ import pl.touk.nussknacker.engine.definition.component.{ComponentStaticDefinitio
import pl.touk.nussknacker.engine.util.Implicits.RichScalaMap
import pl.touk.nussknacker.engine.ModelData
import pl.touk.nussknacker.restmodel.definition._
import pl.touk.nussknacker.ui.definition.DefinitionsService.{createUIParameter, createUIScenarioPropertyConfig}
import pl.touk.nussknacker.ui.definition.DefinitionsService.{
ComponentUiConfigMode,
createUIParameter,
createUIScenarioPropertyConfig
}
import pl.touk.nussknacker.ui.definition.component.{ComponentGroupsPreparer, ComponentWithStaticDefinition}
import pl.touk.nussknacker.ui.definition.scenarioproperty.{FragmentPropertiesConfig, UiScenarioPropertyEditorDeterminer}
import pl.touk.nussknacker.ui.process.fragment.FragmentRepository
import pl.touk.nussknacker.ui.process.processingtype.ProcessingTypeData
import pl.touk.nussknacker.ui.process.processingtype.{DesignerModelData, ProcessingTypeData}
import pl.touk.nussknacker.ui.security.api.LoggedUser

import scala.concurrent.{ExecutionContext, Future}
Expand All @@ -23,7 +27,7 @@ import scala.concurrent.{ExecutionContext, Future}
// enters the scenario view. The core domain logic should be done during Model definition extraction
class DefinitionsService(
modelData: ModelData,
staticDefinitionForDynamicComponents: Map[ComponentId, ComponentStaticDefinition],
staticDefinitionForDynamicComponents: DesignerModelData.DynamicComponentsStaticDefinitions,
scenarioPropertiesConfig: Map[String, ScenarioPropertyConfig],
fragmentPropertiesConfig: Map[String, ScenarioPropertyConfig],
deploymentManager: DeploymentManager,
Expand All @@ -33,29 +37,51 @@ class DefinitionsService(
fragmentPropertiesDocsUrl: Option[String]
)(implicit ec: ExecutionContext) {

def prepareUIDefinitions(processingType: ProcessingType, forFragment: Boolean)(
def prepareUIDefinitions(
processingType: ProcessingType,
forFragment: Boolean,
componentUiConfigMode: ComponentUiConfigMode
)(
implicit user: LoggedUser
): Future[UIDefinitions] = {
fragmentRepository.fetchLatestFragments(processingType).map { fragments =>
val alignedComponentsDefinition =
alignedComponentsDefinitionProvider
.getAlignedComponentsWithBuiltInComponentsAndFragments(forFragment, fragments)

val withStaticDefinition = alignedComponentsDefinition.map {
case dynamic: DynamicComponentDefinitionWithImplementation =>
val staticDefinition = staticDefinitionForDynamicComponents.getOrElse(
dynamic.id,
throw new IllegalStateException(s"Static definition for dynamic component: $dynamic should be precomputed")
)
ComponentWithStaticDefinition(dynamic, staticDefinition)
case methodBased: MethodBasedComponentDefinitionWithImplementation =>
ComponentWithStaticDefinition(methodBased, methodBased.staticDefinition)
case other =>
throw new IllegalStateException(s"Unknown component representation: $other")
val withStaticDefinition = {
val (components, cachedStaticDefinitionsForDynamicComponents) = componentUiConfigMode match {
case ComponentUiConfigMode.EnrichedWithUiConfig =>
(alignedComponentsDefinition.components, staticDefinitionForDynamicComponents.finalDefinitions)
case ComponentUiConfigMode.BasicConfig =>
(
alignedComponentsDefinition.basicComponentsUnsafe,
staticDefinitionForDynamicComponents.basicDefinitionsUnsafe
)
}

components.map {
case dynamic: DynamicComponentDefinitionWithImplementation =>
val staticDefinition = cachedStaticDefinitionsForDynamicComponents.getOrElse(
dynamic.id,
throw new IllegalStateException(
s"Static definition for dynamic component: $dynamic should be precomputed"
)
)
ComponentWithStaticDefinition(dynamic, staticDefinition)
case methodBased: MethodBasedComponentDefinitionWithImplementation =>
ComponentWithStaticDefinition(methodBased, methodBased.staticDefinition)
case other =>
throw new IllegalStateException(s"Unknown component representation: $other")
}
}

val finalizedScenarioPropertiesConfig = scenarioPropertiesConfigFinalizer
.finalizeScenarioProperties(scenarioPropertiesConfig)
val finalizedScenarioPropertiesConfig = componentUiConfigMode match {
case ComponentUiConfigMode.EnrichedWithUiConfig =>
scenarioPropertiesConfigFinalizer.finalizeScenarioProperties(scenarioPropertiesConfig)
case ComponentUiConfigMode.BasicConfig =>
scenarioPropertiesConfig
}

import net.ceedubs.ficus.Ficus._
val scenarioPropertiesDocsUrl = modelData.modelConfig.getAs[String]("scenarioPropertiesDocsUrl")
Expand Down Expand Up @@ -143,7 +169,8 @@ object DefinitionsService {
variablesToHide = parameter.variablesToHide,
branchParam = parameter.branchParam,
hintText = parameter.hintText,
label = parameter.label
label = parameter.label,
requiredParam = !parameter.isOptional,
)
}

Expand All @@ -152,4 +179,11 @@ object DefinitionsService {
UiScenarioPropertyConfig(config.defaultValue, editor, config.label, config.hintText)
}

sealed trait ComponentUiConfigMode

object ComponentUiConfigMode {
case object EnrichedWithUiConfig extends ComponentUiConfigMode
case object BasicConfig extends ComponentUiConfigMode
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ class DefaultComponentService(
forFragment = false, // It excludes fragment's components: input / output
fragments
)
.components

private def createComponentLinks(
designerWideId: DesignerWideComponentId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package pl.touk.nussknacker.ui.process.processingtype
import pl.touk.nussknacker.engine.ModelData
import pl.touk.nussknacker.engine.api.component.{ComponentId, ProcessingMode}
import pl.touk.nussknacker.engine.definition.component.ComponentStaticDefinition
import pl.touk.nussknacker.ui.process.processingtype.DesignerModelData.DynamicComponentsStaticDefinitions

final case class DesignerModelData(
modelData: ModelData,
// We hold this map as a cache - computing it is a quite costly operation (it invokes external services)
staticDefinitionForDynamicComponents: Map[ComponentId, ComponentStaticDefinition],
// We hold definitions as a cache - computing them is a quite costly operation (it invokes external services)
staticDefinitionForDynamicComponents: DynamicComponentsStaticDefinitions,
processingMode: ProcessingMode
) {

Expand All @@ -16,3 +17,20 @@ final case class DesignerModelData(
}

}

object DesignerModelData {

final case class DynamicComponentsStaticDefinitions(
finalDefinitions: Map[ComponentId, ComponentStaticDefinition],
// component definitions not enriched with ui config
private val basicDefinitions: Option[Map[ComponentId, ComponentStaticDefinition]]
) {

def basicDefinitionsUnsafe: Map[ComponentId, ComponentStaticDefinition] =
basicDefinitions.getOrElse(
throw new IllegalStateException("Basic definitions were requested but they are not precomputed")
)

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ import pl.touk.nussknacker.engine._
import pl.touk.nussknacker.engine.api.component.ScenarioPropertyConfig
import pl.touk.nussknacker.engine.api.deployment.cache.ScenarioStateCachingConfig
import pl.touk.nussknacker.engine.api.process.ProcessingType
import pl.touk.nussknacker.engine.definition.component.DynamicComponentStaticDefinitionDeterminer
import pl.touk.nussknacker.engine.definition.component.Components.ComponentDefinitionExtractionMode
import pl.touk.nussknacker.engine.definition.component.{
ComponentDefinitionWithImplementation,
Components,
DynamicComponentStaticDefinitionDeterminer
}
import pl.touk.nussknacker.engine.deployment.EngineSetupName
import pl.touk.nussknacker.restmodel.scenariodetails.ScenarioParameters
import pl.touk.nussknacker.ui.process.processingtype.DesignerModelData.DynamicComponentsStaticDefinitions

import scala.util.control.NonFatal

Expand Down Expand Up @@ -50,7 +56,8 @@ object ProcessingTypeData {
deploymentManagerDependencies: DeploymentManagerDependencies,
engineSetupName: EngineSetupName,
deploymentConfig: Config,
category: String
category: String,
componentDefinitionExtractionMode: ComponentDefinitionExtractionMode
): ProcessingTypeData = {
try {
val metaDataInitializer = deploymentManagerProvider.metaDataInitializer(deploymentConfig)
Expand All @@ -64,7 +71,8 @@ object ProcessingTypeData {
metaDataInitializer
)

val designerModelData = createDesignerModelData(modelData, metaDataInitializer, name)
val designerModelData =
createDesignerModelData(modelData, metaDataInitializer, name, componentDefinitionExtractionMode)
ProcessingTypeData(
name,
designerModelData,
Expand Down Expand Up @@ -117,17 +125,42 @@ object ProcessingTypeData {
private def createDesignerModelData(
modelData: ModelData,
metaDataInitializer: MetaDataInitializer,
processingType: ProcessingType
processingType: ProcessingType,
componentDefinitionExtractionMode: ComponentDefinitionExtractionMode
) = {

val staticDefinitionForDynamicComponents =
createDynamicComponentsStaticDefinitions(modelData, metaDataInitializer, componentDefinitionExtractionMode)

val singleProcessingMode =
ScenarioParametersDeterminer.determineProcessingMode(
modelData.modelDefinition.components.components,
processingType
)
DesignerModelData(modelData, staticDefinitionForDynamicComponents, singleProcessingMode)
}

private def createDynamicComponentsStaticDefinitions(
modelData: ModelData,
metaDataInitializer: MetaDataInitializer,
componentDefinitionExtractionMode: ComponentDefinitionExtractionMode
): DynamicComponentsStaticDefinitions = {
def createStaticDefinitions(extractComponents: Components => List[ComponentDefinitionWithImplementation]) = {
DynamicComponentStaticDefinitionDeterminer.collectStaticDefinitionsForDynamicComponents(
modelData,
metaDataInitializer.create(_, Map.empty)
metaDataInitializer.create(_, Map.empty),
extractComponents
)
}

val singleProcessingMode =
ScenarioParametersDeterminer.determineProcessingMode(modelData.modelDefinition.components, processingType)
DesignerModelData(modelData, staticDefinitionForDynamicComponents, singleProcessingMode)
DynamicComponentsStaticDefinitions(
finalDefinitions = createStaticDefinitions(_.components),
basicDefinitions = componentDefinitionExtractionMode match {
case ComponentDefinitionExtractionMode.FinalDefinition => None
case ComponentDefinitionExtractionMode.FinalAndBasicDefinitions =>
Some(createStaticDefinitions(_.basicComponentsUnsafe))
}
)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class LocalProcessingTypeDataLoader(
engineSetupName = deploymentManagerProvider.defaultEngineSetupName,
deploymentConfig = ConfigFactory.empty(),
category = category,
componentDefinitionExtractionMode = getModelDependencies(processingType).componentDefinitionExtractionMode
)
processingType -> data
}
Expand Down
Loading
Loading