Skip to content

Commit

Permalink
[NU-1828] Processing types configs loader api (#7336)
Browse files Browse the repository at this point in the history
  • Loading branch information
arkadius authored Dec 17, 2024
1 parent 5970344 commit a5d5305
Show file tree
Hide file tree
Showing 35 changed files with 505 additions and 359 deletions.
54 changes: 34 additions & 20 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import com.typesafe.sbt.packager.SettingsHelper
import com.typesafe.sbt.packager.docker.DockerPlugin.autoImport.dockerUsername
import pl.project13.scala.sbt.JmhPlugin
import pl.project13.scala.sbt.JmhPlugin._
import sbt.Keys._
import sbt._
import pl.project13.scala.sbt.JmhPlugin.*
import sbt.*
import sbt.Keys.*
import sbtassembly.AssemblyPlugin.autoImport.assembly
import sbtassembly.MergeStrategy
import sbtrelease.ReleasePlugin.autoImport.ReleaseTransformations._
import sbtrelease.ReleasePlugin.autoImport.ReleaseTransformations.*

import scala.language.postfixOps
import scala.sys.process._
import scala.sys.process.*
import scala.util.Try
import scala.xml.Elem
import scala.xml.transform.{RewriteRule, RuleTransformer}
Expand Down Expand Up @@ -1913,6 +1913,18 @@ lazy val listenerApi = (project in file("designer/listener-api"))
)
.dependsOn(extensionsApi)

lazy val configLoaderApi = (project in file("designer/config-loader-api"))
.settings(commonSettings)
.settings(
name := "nussknacker-config-loader-api",
libraryDependencies ++= {
Seq(
"org.typelevel" %% "cats-effect" % catsEffectV
)
}
)
.dependsOn(extensionsApi)

lazy val deploymentManagerApi = (project in file("designer/deployment-manager-api"))
.settings(commonSettings)
.settings(
Expand Down Expand Up @@ -1985,21 +1997,21 @@ lazy val designer = (project in file("designer/server"))
assembly / assemblyMergeStrategy := designerMergeStrategy,
libraryDependencies ++= {
Seq(
"com.typesafe.akka" %% "akka-http" % akkaHttpV,
"com.typesafe.akka" %% "akka-slf4j" % akkaV,
"com.typesafe.akka" %% "akka-stream" % akkaV,
"com.typesafe.akka" %% "akka-http-testkit" % akkaHttpV % Test,
"com.typesafe.akka" %% "akka-testkit" % akkaV % Test,
"de.heikoseeberger" %% "akka-http-circe" % akkaHttpCirceV,
"com.softwaremill.sttp.client3" %% "akka-http-backend" % sttpV,
"ch.qos.logback" % "logback-core" % logbackV,
"ch.qos.logback" % "logback-classic" % logbackV,
"ch.qos.logback.contrib" % "logback-json-classic" % logbackJsonV,
"ch.qos.logback.contrib" % "logback-jackson" % logbackJsonV,
"com.fasterxml.jackson.core" % "jackson-databind" % jacksonV,
"org.slf4j" % "log4j-over-slf4j" % slf4jV,
"com.carrotsearch" % "java-sizeof" % "0.0.5",
"org.typelevel" %% "case-insensitive" % "1.4.0",
"com.typesafe.akka" %% "akka-http" % akkaHttpV,
"com.typesafe.akka" %% "akka-slf4j" % akkaV,
"com.typesafe.akka" %% "akka-stream" % akkaV,
"com.typesafe.akka" %% "akka-http-testkit" % akkaHttpV % Test,
"com.typesafe.akka" %% "akka-testkit" % akkaV % Test,
"de.heikoseeberger" %% "akka-http-circe" % akkaHttpCirceV,
"com.softwaremill.sttp.client3" %% "async-http-client-backend-cats" % sttpV,
"ch.qos.logback" % "logback-core" % logbackV,
"ch.qos.logback" % "logback-classic" % logbackV,
"ch.qos.logback.contrib" % "logback-json-classic" % logbackJsonV,
"ch.qos.logback.contrib" % "logback-jackson" % logbackJsonV,
"com.fasterxml.jackson.core" % "jackson-databind" % jacksonV,
"org.slf4j" % "log4j-over-slf4j" % slf4jV,
"com.carrotsearch" % "java-sizeof" % "0.0.5",
"org.typelevel" %% "case-insensitive" % "1.4.0",

// It's needed by flinkDeploymentManager which has disabled includingScala
"org.scala-lang" % "scala-compiler" % scalaVersion.value,
Expand Down Expand Up @@ -2053,6 +2065,7 @@ lazy val designer = (project in file("designer/server"))
deploymentManagerApi,
restmodel,
listenerApi,
configLoaderApi,
defaultHelpers % Test,
testUtils % Test,
flinkTestUtils % Test,
Expand Down Expand Up @@ -2193,6 +2206,7 @@ lazy val modules = List[ProjectReference](
httpUtils,
restmodel,
listenerApi,
configLoaderApi,
deploymentManagerApi,
designer,
sqlComponents,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package pl.touk.nussknacker.ui.configloader

import cats.effect.IO
import pl.touk.nussknacker.engine.ProcessingTypeConfig

trait ProcessingTypeConfigsLoader {

def loadProcessingTypeConfigs(): IO[ProcessingTypeConfigs]

}

case class ProcessingTypeConfigs(configByProcessingType: Map[String, ProcessingTypeConfig])
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package pl.touk.nussknacker.ui.configloader

import cats.effect.IO
import cats.effect.unsafe.IORuntime
import com.typesafe.config.Config
import sttp.client3.SttpBackend

trait ProcessingTypeConfigsLoaderFactory {

def create(
configLoaderConfig: Config,
sttpBackend: SttpBackend[IO, Any],
)(implicit ec: IORuntime): ProcessingTypeConfigsLoader

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

import cats.effect.{IO, Resource}
import com.typesafe.config.{Config, ConfigFactory}
import com.typesafe.config.{Config, ConfigFactory, ConfigValue, ConfigValueFactory}
import org.apache.commons.io.FileUtils
import pl.touk.nussknacker.engine.{DeploymentManagerProvider, ModelData}
import pl.touk.nussknacker.ui.config.DesignerConfigLoader
Expand Down Expand Up @@ -49,8 +49,14 @@ object LocalNussknackerWithSingleModel {
modelData = Map(typeName -> (category, modelData)),
deploymentManagerProvider = deploymentManagerProvider
)
val nussknackerConfig = new LoadableConfigBasedNussknackerConfig(IO.delay(DesignerConfigLoader.from(appConfig)))
val appFactory = new NussknackerAppFactory(nussknackerConfig, local)
val designerConfigLoader = DesignerConfigLoader.fromConfig(
// This map is ignored but must exist
appConfig.withValue("scenarioTypes", ConfigValueFactory.fromMap(Map.empty[String, ConfigValue].asJava))
)
val appFactory = new NussknackerAppFactory(
designerConfigLoader,
_ => local
)
appFactory.createApp()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package pl.touk.nussknacker.ui

import cats.effect.{ExitCode, IO, IOApp}
import pl.touk.nussknacker.ui.config.{AlwaysLoadingFileBasedDesignerConfigLoader, DesignerConfigLoader}
import pl.touk.nussknacker.ui.factory.NussknackerAppFactory

object NussknackerApp extends IOApp {

override def run(args: List[String]): IO[ExitCode] = {
for {
appFactory <- IO(new NussknackerAppFactory(getClass.getClassLoader))
appFactory <- IO(NussknackerAppFactory(AlwaysLoadingFileBasedDesignerConfigLoader(getClass.getClassLoader)))
_ <- appFactory.createApp().use { _ => IO.never }
} yield ExitCode.Success
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ import pl.touk.nussknacker.ui.api.description.DictApiEndpoints.DictError.{
}
import pl.touk.nussknacker.ui.api.description.DictApiEndpoints.Dtos._
import sttp.model.StatusCode.{BadRequest, NotFound, Ok}
import sttp.tapir._
import sttp.tapir.json.circe._
import sttp.tapir.Schema
import sttp.tapir._

import scala.language.implicitConversions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import pl.touk.nussknacker.restmodel.BaseEndpointDefinitions
import pl.touk.nussknacker.restmodel.BaseEndpointDefinitions.SecuredEndpoint
import pl.touk.nussknacker.security.AuthCredentials
import pl.touk.nussknacker.ui.security.api.GlobalPermission.GlobalPermission
import pl.touk.nussknacker.ui.security.api.{AdminUser, CommonUser, ImpersonatedUser, LoggedUser, RealLoggedUser}
import pl.touk.nussknacker.ui.security.api._
import sttp.model.StatusCode.Ok
import sttp.tapir.EndpointIO.Example
import sttp.tapir.derevo.schema
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package pl.touk.nussknacker.ui.api.description.scenarioActivity
import pl.touk.nussknacker.engine.api.process.ProcessName
import pl.touk.nussknacker.ui.api.description.scenarioActivity.Dtos.ScenarioActivityError
import pl.touk.nussknacker.ui.api.description.scenarioActivity.Dtos.ScenarioActivityError.NoScenario
import sttp.model.StatusCode.{NotFound, NotImplemented}
import sttp.model.StatusCode.NotFound
import sttp.tapir.EndpointIO.Example
import sttp.tapir.{EndpointOutput, emptyOutputAs, oneOf, oneOfVariantFromMatchType, plainBody}
import sttp.tapir.{EndpointOutput, oneOf, oneOfVariantFromMatchType, plainBody}

object InputOutput {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package pl.touk.nussknacker.ui.config

import com.typesafe.config.{Config, ConfigFactory}
import pl.touk.nussknacker.engine.util.Implicits.RichScalaMap
import pl.touk.nussknacker.engine.{ConfigWithUnresolvedVersion, ProcessingTypeConfig}
import pl.touk.nussknacker.ui.configloader.ProcessingTypeConfigs

// TODO: We should extract a class for all configuration options that should be available to designer instead of returning raw hocon config.
// Thanks to that it will be easier to split processing type config from rest of configs and use this interface programmatically
final case class DesignerConfig private (rawConfig: ConfigWithUnresolvedVersion) {

import net.ceedubs.ficus.Ficus._

def processingTypeConfigs: ProcessingTypeConfigs =
ProcessingTypeConfigs(
rawConfig
.readMap("scenarioTypes")
.getOrElse {
throw new RuntimeException("No scenario types configuration provided")
}
.mapValuesNow(ProcessingTypeConfig.read)
)

def configLoaderConfig: Config = rawConfig.resolved.getAs[Config]("configLoader").getOrElse(ConfigFactory.empty())

}

object DesignerConfig {

def from(config: Config): DesignerConfig = {
DesignerConfig(ConfigWithUnresolvedVersion(config))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ package pl.touk.nussknacker.ui.config
import cats.effect.IO
import com.typesafe.config.{Config, ConfigFactory}
import pl.touk.nussknacker.engine.ConfigWithUnresolvedVersion
import pl.touk.nussknacker.engine.util.UriUtils
import pl.touk.nussknacker.engine.util.config.ConfigFactoryExt

trait DesignerConfigLoader {

def loadDesignerConfig(): IO[DesignerConfig]

}

/**
* This class handles two parts of ui config loading:
* 1. Parsing of "base" config passed via nussknacker.config.locations system property (without resolution)
Expand All @@ -14,27 +21,43 @@ import pl.touk.nussknacker.engine.util.config.ConfigFactoryExt
* Result of config loading still keep version with unresolved env variables for purpose of config loading on model side - see
* InputConfigDuringExecution and ModelConfigLoader
*/
object DesignerConfigLoader {
class AlwaysLoadingFileBasedDesignerConfigLoader private (classLoader: ClassLoader) extends DesignerConfigLoader {

private val configLocationsProperty: String = "nussknacker.config.locations"

private val defaultConfigResource = "defaultDesignerConfig.conf"

def load(classLoader: ClassLoader): IO[ConfigWithUnresolvedVersion] = {
override def loadDesignerConfig(): IO[DesignerConfig] = {
val locationsPropertyValueOpt = Option(System.getProperty(configLocationsProperty))
val locations = locationsPropertyValueOpt.map(UriUtils.extractListOfLocations).getOrElse(List.empty)
for {
baseConfig <- IO.blocking(ConfigFactoryExt.parseUnresolved(classLoader = classLoader))
loadedConfig <- load(baseConfig, classLoader)
} yield loadedConfig
baseUnresolvedConfig <- IO.blocking(new ConfigFactoryExt(classLoader).parseUnresolved(locations))
parsedDefaultUiConfig <- IO.blocking(ConfigFactory.parseResources(classLoader, defaultConfigResource))
unresolvedConfigWithFallbackToDefaults = baseUnresolvedConfig.withFallback(parsedDefaultUiConfig)
} yield DesignerConfig(ConfigWithUnresolvedVersion(classLoader, unresolvedConfigWithFallbackToDefaults))
}

def load(baseUnresolvedConfig: Config, classLoader: ClassLoader): IO[ConfigWithUnresolvedVersion] = {
IO.blocking {
val parsedDefaultUiConfig = ConfigFactory.parseResources(classLoader, defaultConfigResource)
val unresolvedConfigWithFallbackToDefaults = baseUnresolvedConfig.withFallback(parsedDefaultUiConfig)
ConfigWithUnresolvedVersion(classLoader, unresolvedConfigWithFallbackToDefaults)
}
}
}

def from(config: Config): ConfigWithUnresolvedVersion = {
ConfigWithUnresolvedVersion(this.getClass.getClassLoader, config)
}
object AlwaysLoadingFileBasedDesignerConfigLoader {

def apply(classLoader: ClassLoader): AlwaysLoadingFileBasedDesignerConfigLoader =
new AlwaysLoadingFileBasedDesignerConfigLoader(classLoader)

}

/**
* This implementation is more straightforward - it only parse config without any property checking and fallbacks
*/
class SimpleConfigLoadingDesignerConfigLoader(loadConfig: => Config) extends DesignerConfigLoader {

override def loadDesignerConfig(): IO[DesignerConfig] = IO.delay(DesignerConfig.from(loadConfig))

}

object DesignerConfigLoader {

def fromConfig(loadConfig: => Config): SimpleConfigLoadingDesignerConfigLoader =
new SimpleConfigLoadingDesignerConfigLoader(loadConfig)

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import pl.touk.nussknacker.engine.api.deployment.{
}
import pl.touk.nussknacker.engine.api.process.{ProcessId, ProcessName, VersionId}
import pl.touk.nussknacker.engine.newdeployment.DeploymentId
import slick.ast.BaseTypedType
import slick.jdbc.{JdbcProfile, JdbcType}
import slick.jdbc.JdbcProfile

import java.util.UUID

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package pl.touk.nussknacker.ui.db.entity

import pl.touk.nussknacker.engine.api.process.{ProcessId, ProcessName}
import pl.touk.nussknacker.engine.api.process.ProcessingType
import pl.touk.nussknacker.engine.api.process.{ProcessId, ProcessName, ProcessingType}
import slick.lifted.{ProvenShape, TableQuery => LTableQuery}
import slick.sql.SqlProfile.ColumnOption.NotNull

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import io.questdb.cairo.security.AllowAllSecurityContext
import io.questdb.cairo.sql.RecordCursorFactory
import io.questdb.cairo.wal.WalWriter
import io.questdb.griffin.{SqlExecutionContext, SqlExecutionContextImpl}
import pl.touk.nussknacker.ui.db.timeseries.{FEStatisticsRepository, NoOpFEStatisticsRepository}
import pl.touk.nussknacker.ui.db.timeseries.questdb.QuestDbExtensions.{
BuildCairoEngineExtension,
CairoEngineExtension,
Expand All @@ -22,6 +21,7 @@ import pl.touk.nussknacker.ui.db.timeseries.questdb.QuestDbFEStatisticsRepositor
selectQuery,
tableName
}
import pl.touk.nussknacker.ui.db.timeseries.{FEStatisticsRepository, NoOpFEStatisticsRepository}
import pl.touk.nussknacker.ui.statistics.RawFEStatistics

import java.time.Clock
Expand Down
Loading

0 comments on commit a5d5305

Please sign in to comment.