Skip to content

Commit

Permalink
Merge pull request #1404 from factcast/issue1104
Browse files Browse the repository at this point in the history
#1104 Use Transformer (pgsql) for schema-registry cli
  • Loading branch information
uweschaefer committed Jul 23, 2021
2 parents 65b7ad4 + 0aa99d1 commit cf426af
Show file tree
Hide file tree
Showing 43 changed files with 1,284 additions and 1,281 deletions.
902 changes: 481 additions & 421 deletions factcast-schema-registry-cli/pom.xml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.factcast.schema.registry.cli.config

import io.micronaut.context.annotation.Bean
import io.micronaut.context.annotation.Factory
import org.factcast.store.pgsql.registry.transformation.chains.NashornTransformer
import org.factcast.store.pgsql.registry.transformation.chains.Transformer

@Factory
class TransformerConfig {
@Bean
fun transformer(): Transformer = NashornTransformer()
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,26 @@
package org.factcast.schema.registry.cli.utils

import arrow.core.Either
import arrow.core.Left
import arrow.core.Right
import com.github.fge.jsonschema.core.exceptions.ProcessingException
import com.github.fge.jsonschema.main.JsonSchema
import com.github.fge.jsonschema.main.JsonSchemaFactory
import java.nio.file.Path
import javax.inject.Singleton
import org.factcast.schema.registry.cli.fs.FileSystemService
import org.factcast.schema.registry.cli.validation.ProjectError
import java.nio.file.Path
import javax.inject.Singleton

@Singleton
class SchemaServiceImpl(
private val fileSystemService: FileSystemService,
private val jsonSchemaFactory: JsonSchemaFactory
) : SchemaService {
override fun loadSchema(path: Path): Either<ProjectError, JsonSchema> {
val jsonNode = fileSystemService.readToJsonNode(path) ?: return Left(ProjectError.NoSuchFile(path))
val jsonNode = fileSystemService.readToJsonNode(path) ?: return Either.Left(ProjectError.NoSuchFile(path))

return try {
Right(jsonSchemaFactory.getJsonSchema(jsonNode))
Either.Right(jsonSchemaFactory.getJsonSchema(jsonNode))
} catch (e: ProcessingException) {
Left(ProjectError.CorruptedSchema(path))
Either.Left(ProjectError.CorruptedSchema(path))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,38 @@
package org.factcast.schema.registry.cli.validation

import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import jdk.nashorn.api.scripting.ScriptObjectMirror
import java.nio.file.Path
import org.factcast.schema.registry.cli.domain.Event
import org.factcast.schema.registry.cli.domain.Namespace
import org.factcast.schema.registry.cli.domain.Transformation
import org.factcast.schema.registry.cli.fs.FileSystemService
import org.factcast.store.pgsql.registry.transformation.SingleTransformation
import org.factcast.store.pgsql.registry.transformation.TransformationKey
import org.factcast.store.pgsql.registry.transformation.chains.TransformationChain
import org.factcast.store.pgsql.registry.transformation.chains.Transformer
import javax.inject.Singleton
import org.factcast.schema.registry.cli.js.JsFunctionExecutor

@Singleton
class TransformationEvaluator(
private val jsFunctionExecutor: JsFunctionExecutor,
private val om: ObjectMapper
private val transformer: Transformer,
private val fs: FileSystemService
) {
fun evaluate(pathToTransformation: Path, data: JsonNode): JsonNode {
val dataAsMap = om.treeToValue(data, Map::class.java)
fun evaluate(ns: Namespace, event: Event, transformation: Transformation, data: JsonNode): JsonNode {
val key = TransformationKey.of(ns.name, event.type)
val singleTransformation =
SingleTransformation.of(
key,
transformation.from,
transformation.to,
fs.readToString(transformation.transformationPath.toFile())
)
val chain = TransformationChain.of(
key,
listOf(singleTransformation),
"no-real-meaning"
)

val result = jsFunctionExecutor.execute("transform", pathToTransformation, dataAsMap)

// when the transform script added an array to an object, it has the type ScriptObjectMirror with isArray=true
// but is internally a map of idx -> value
// Jackson transforms this into an object with index as key, not an array. So find and fix this:
val fixedResult = fixArrayTransformations(result)

return om.valueToTree(fixedResult)
return transformer.transform(chain, data)
}

fun fixArrayTransformations(data: Map<*, *>): Map<*, *> {
return data.mapValues {
if (it.value is ScriptObjectMirror && (it.value as ScriptObjectMirror).isArray) {
(it.value as ScriptObjectMirror).to(List::class.java)
} else if (it.value is Map<*, *>) {
fixArrayTransformations(it.value as Map<*, *>)
} else {
it.value
}
};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@
package org.factcast.schema.registry.cli.validation

import arrow.core.Either
import arrow.core.Left
import arrow.core.Right
import arrow.core.flatMap
import javax.inject.Singleton
import org.factcast.schema.registry.cli.domain.Project
import org.factcast.schema.registry.cli.project.structure.ProjectFolder
import org.factcast.schema.registry.cli.validation.validators.ExampleValidationService
import org.factcast.schema.registry.cli.validation.validators.ProjectStructureValidationService
import org.factcast.schema.registry.cli.validation.validators.TransformationValidationService
import javax.inject.Singleton

@Singleton
class ValidationServiceImpl(
Expand All @@ -40,9 +38,9 @@ class ValidationServiceImpl(
.plus(transformationValidationService.validateTransformations(it))

if (errors.isEmpty()) {
Right(it)
Either.Right(it)
} else {
Left(errors)
Either.Left(errors)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,14 @@
package org.factcast.schema.registry.cli.validation.validators.impl

import arrow.core.Either
import arrow.core.Left
import arrow.core.Right
import javax.inject.Singleton
import javax.validation.Validator
import org.factcast.schema.registry.cli.domain.Project
import org.factcast.schema.registry.cli.project.structure.Folder
import org.factcast.schema.registry.cli.project.structure.ProjectFolder
import org.factcast.schema.registry.cli.project.structure.toProject
import org.factcast.schema.registry.cli.validation.NO_DESCRIPTION
import org.factcast.schema.registry.cli.validation.NO_EVENTS
import org.factcast.schema.registry.cli.validation.NO_EVENT_VERSIONS
import org.factcast.schema.registry.cli.validation.NO_EXAMPLES
import org.factcast.schema.registry.cli.validation.NO_NAMESPACES
import org.factcast.schema.registry.cli.validation.NO_SCHEMA
import org.factcast.schema.registry.cli.validation.NO_TRANSFORMATION_FILE
import org.factcast.schema.registry.cli.validation.ProjectError
import org.factcast.schema.registry.cli.validation.TRANSFORMATION_VERSION_INVALID
import org.factcast.schema.registry.cli.validation.VERSION_INVALID
import org.factcast.schema.registry.cli.validation.*
import org.factcast.schema.registry.cli.validation.validators.ProjectStructureValidationService
import javax.inject.Singleton
import javax.validation.Validator

@Singleton
class ProjectStructureValidationServiceImpl(private val validator: Validator) : ProjectStructureValidationService {
Expand Down Expand Up @@ -67,9 +56,9 @@ class ProjectStructureValidationServiceImpl(private val validator: Validator) :
}

return if (errors.isNotEmpty())
Left(errors)
Either.Left(errors)
else {
Right(
Either.Right(
projectFolder.toProject()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.factcast.schema.registry.cli.validation.validators.impl

import com.google.common.annotations.VisibleForTesting
import javax.inject.Singleton
import org.factcast.schema.registry.cli.domain.Project
import org.factcast.schema.registry.cli.fs.FileSystemService
import org.factcast.schema.registry.cli.utils.SchemaService
Expand All @@ -26,6 +25,7 @@ import org.factcast.schema.registry.cli.validation.MissingTransformationCalculat
import org.factcast.schema.registry.cli.validation.ProjectError
import org.factcast.schema.registry.cli.validation.TransformationEvaluator
import org.factcast.schema.registry.cli.validation.validators.TransformationValidationService
import javax.inject.Singleton

@Singleton
class TransformationValidationServiceImpl(
Expand All @@ -46,7 +46,7 @@ class TransformationValidationServiceImpl(
}

@VisibleForTesting
fun calculateValidationErrors(project: Project) = project.mapEventTransformations { _, event, transformation ->
fun calculateValidationErrors(project: Project) = project.mapEventTransformations { ns, event, transformation ->
val fromVersion = event.versions.find { it.version == transformation.from }
val toVersion = event.versions.find { it.version == transformation.to }

Expand All @@ -68,7 +68,7 @@ class TransformationValidationServiceImpl(
.fold({ listOf(it) }, { schema ->
examples.mapNotNull {
val transformationResult =
transformationEvaluator.evaluate(transformation.transformationPath, it)
transformationEvaluator.evaluate(ns, event, transformation, it)

val validationResult = schema.validate(
transformationResult
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,15 @@ package org.factcast.schema.registry.cli.validation.validators.impl
import io.micronaut.core.annotation.AnnotationValue
import io.micronaut.validation.validator.constraints.ConstraintValidator
import io.micronaut.validation.validator.constraints.ConstraintValidatorContext
import org.factcast.schema.registry.cli.validation.validators.ValidTransformationFolder
import java.nio.file.Path
import javax.inject.Singleton
import org.factcast.schema.registry.cli.validation.validators.ValidTransformationFolder

@Singleton
class ValidTransformationFolderValidator : ConstraintValidator<ValidTransformationFolder, Path> {
override fun isValid(
value: Path?,
annotationMetadata: AnnotationValue<ValidTransformationFolder>,
context: ConstraintValidatorContext
) = value != null && try {
val splitted = value.fileName.toString().split("-")

if (splitted.size != 2) {
false
} else {
val (from, to) = splitted

from.toInt()
to.toInt()

true
}
} catch (e: NumberFormatException) {
false
}
) = (value == null || Regex("[0-9]+-[0-9]+").matches(value.fileName.toString()))
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ package org.factcast.schema.registry.cli.whitelistfilter
import org.factcast.schema.registry.cli.project.structure.ProjectFolder

interface WhiteListFilterService {
fun filter(project: ProjectFolder, whiteList: List<String>): ProjectFolder
fun filter(project: ProjectFolder, whiteListEntries: List<String>): ProjectFolder
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.kotlintest.provided

import io.kotest.core.config.AbstractProjectConfig
import io.micronaut.test.extensions.kotest.MicronautKotestExtension

object ProjectConfig : AbstractProjectConfig() {
override fun listeners() = listOf(MicronautKotestExtension)
override fun extensions() = listOf(MicronautKotestExtension)
}

0 comments on commit cf426af

Please sign in to comment.