diff --git a/analytics/pom.xml b/analytics/pom.xml index a4981c671c..508379eec2 100644 --- a/analytics/pom.xml +++ b/analytics/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT analytics diff --git a/auth-common/pom.xml b/auth-common/pom.xml index ca221528c1..d7bba4cecc 100644 --- a/auth-common/pom.xml +++ b/auth-common/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/auth-tokens/pom.xml b/auth-tokens/pom.xml index d3df3db561..810d9b9a47 100644 --- a/auth-tokens/pom.xml +++ b/auth-tokens/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT auth-tokens diff --git a/avro-message-format/pom.xml b/avro-message-format/pom.xml index a76742180f..9898731a7e 100644 --- a/avro-message-format/pom.xml +++ b/avro-message-format/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT avro-message-format diff --git a/cockpit-core/pom.xml b/cockpit-core/pom.xml index bc4a70af1a..cc5d67c093 100644 --- a/cockpit-core/pom.xml +++ b/cockpit-core/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT cockpit-core @@ -221,7 +221,7 @@ com.orbitalhq query-node-core - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.taxilang @@ -434,11 +434,11 @@ - - com.orbitalhq - test-cli - ${project.version} - + + + + + org.jetbrains.kotlinx diff --git a/cockpit-core/src/main/java/com/orbitalhq/cockpit/core/security/authentication/oidc/PropelAuthApiKeyValidator.kt b/cockpit-core/src/main/java/com/orbitalhq/cockpit/core/security/authentication/oidc/PropelAuthApiKeyValidator.kt index 0c8d126083..bf7c67d638 100644 --- a/cockpit-core/src/main/java/com/orbitalhq/cockpit/core/security/authentication/oidc/PropelAuthApiKeyValidator.kt +++ b/cockpit-core/src/main/java/com/orbitalhq/cockpit/core/security/authentication/oidc/PropelAuthApiKeyValidator.kt @@ -19,6 +19,7 @@ import org.springframework.stereotype.Component import org.springframework.web.client.RestClient import org.springframework.web.client.toEntity import reactor.core.publisher.Mono +import reactor.core.scheduler.Schedulers import java.time.Instant @ConditionalOnProperty("vyne.security.openIdp.roles.format", havingValue = CloudPropelAuthClaimsExtractor.PropelAuthJwtKind, matchIfMissing = false) @@ -83,7 +84,7 @@ class PropelAuthApiKeyValidator( // sink.success(JwtAuthenticationToken( // jwt // )) - } + }.subscribeOn(Schedulers.boundedElastic()) as Mono } diff --git a/connectors/aws-connectors/aws-core/pom.xml b/connectors/aws-connectors/aws-core/pom.xml index 224e40eff6..3da0aae44b 100644 --- a/connectors/aws-connectors/aws-core/pom.xml +++ b/connectors/aws-connectors/aws-core/pom.xml @@ -5,7 +5,7 @@ aws-connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/aws-connectors/dynamo-db-connector/pom.xml b/connectors/aws-connectors/dynamo-db-connector/pom.xml index af8fb5c70b..cc678571e9 100644 --- a/connectors/aws-connectors/dynamo-db-connector/pom.xml +++ b/connectors/aws-connectors/dynamo-db-connector/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq aws-connectors - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT dynamo-db-connector diff --git a/connectors/aws-connectors/lambda-connector/pom.xml b/connectors/aws-connectors/lambda-connector/pom.xml index 82dd3781f0..cd7e5f99cb 100644 --- a/connectors/aws-connectors/lambda-connector/pom.xml +++ b/connectors/aws-connectors/lambda-connector/pom.xml @@ -5,7 +5,7 @@ aws-connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/aws-connectors/pom.xml b/connectors/aws-connectors/pom.xml index 3a26e0ade9..7252669e6b 100644 --- a/connectors/aws-connectors/pom.xml +++ b/connectors/aws-connectors/pom.xml @@ -5,7 +5,7 @@ connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/aws-connectors/s3-connector/pom.xml b/connectors/aws-connectors/s3-connector/pom.xml index 4bcd2183c6..331b5b73dc 100644 --- a/connectors/aws-connectors/s3-connector/pom.xml +++ b/connectors/aws-connectors/s3-connector/pom.xml @@ -5,7 +5,7 @@ aws-connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/aws-connectors/sqs-connector/pom.xml b/connectors/aws-connectors/sqs-connector/pom.xml index 56ab85e793..5a29891c35 100644 --- a/connectors/aws-connectors/sqs-connector/pom.xml +++ b/connectors/aws-connectors/sqs-connector/pom.xml @@ -5,7 +5,7 @@ aws-connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/azure-connectors/blob-connector/pom.xml b/connectors/azure-connectors/blob-connector/pom.xml index b9519a7049..0a6d7ffad5 100644 --- a/connectors/azure-connectors/blob-connector/pom.xml +++ b/connectors/azure-connectors/blob-connector/pom.xml @@ -5,7 +5,7 @@ azure-connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/azure-connectors/pom.xml b/connectors/azure-connectors/pom.xml index f0d3b0910b..be46a88842 100644 --- a/connectors/azure-connectors/pom.xml +++ b/connectors/azure-connectors/pom.xml @@ -5,7 +5,7 @@ connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/azure-connectors/servicebus-connector/pom.xml b/connectors/azure-connectors/servicebus-connector/pom.xml index fbb4c8b959..c1f5ed1159 100644 --- a/connectors/azure-connectors/servicebus-connector/pom.xml +++ b/connectors/azure-connectors/servicebus-connector/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq azure-connectors - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT servicebus-connector diff --git a/connectors/connectors-calcite/pom.xml b/connectors/connectors-calcite/pom.xml index d6e4a16a91..5acfa8fcc2 100644 --- a/connectors/connectors-calcite/pom.xml +++ b/connectors/connectors-calcite/pom.xml @@ -5,7 +5,7 @@ connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -27,7 +27,7 @@ com.orbitalhq datatype-converters - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.taxilang diff --git a/connectors/connectors-core/pom.xml b/connectors/connectors-core/pom.xml index fe57f56278..a1442207a4 100644 --- a/connectors/connectors-core/pom.xml +++ b/connectors/connectors-core/pom.xml @@ -5,7 +5,7 @@ connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/hazelcast-connector/pom.xml b/connectors/hazelcast-connector/pom.xml index 302677312a..71d8e3f105 100644 --- a/connectors/hazelcast-connector/pom.xml +++ b/connectors/hazelcast-connector/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq connectors - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT hazelcast-connector diff --git a/connectors/jdbc-connector/pom.xml b/connectors/jdbc-connector/pom.xml index ce16cea74d..5438d8565c 100644 --- a/connectors/jdbc-connector/pom.xml +++ b/connectors/jdbc-connector/pom.xml @@ -5,7 +5,7 @@ connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/kafka-connector/pom.xml b/connectors/kafka-connector/pom.xml index 43a50a4243..1949fd6a68 100644 --- a/connectors/kafka-connector/pom.xml +++ b/connectors/kafka-connector/pom.xml @@ -5,7 +5,7 @@ connectors com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/nosql-connectors/mongodb-connector/pom.xml b/connectors/nosql-connectors/mongodb-connector/pom.xml index 34cd4ab337..073433f8ee 100644 --- a/connectors/nosql-connectors/mongodb-connector/pom.xml +++ b/connectors/nosql-connectors/mongodb-connector/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq nosql-connectors - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT mongodb-connector diff --git a/connectors/nosql-connectors/pom.xml b/connectors/nosql-connectors/pom.xml index 8cdc5a4c01..87d6c9a147 100644 --- a/connectors/nosql-connectors/pom.xml +++ b/connectors/nosql-connectors/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq connectors - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT nosql-connectors diff --git a/connectors/pom.xml b/connectors/pom.xml index 7a503dde64..1f9bebac93 100644 --- a/connectors/pom.xml +++ b/connectors/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/connectors/soap-connector/pom.xml b/connectors/soap-connector/pom.xml index 3a33f849ff..83e530dd04 100644 --- a/connectors/soap-connector/pom.xml +++ b/connectors/soap-connector/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq connectors - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT soap-connector diff --git a/copilot-api/pom.xml b/copilot-api/pom.xml index 0b4b108c7f..6a83e4511e 100644 --- a/copilot-api/pom.xml +++ b/copilot-api/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT copilot-api diff --git a/copilot/pom.xml b/copilot/pom.xml index 867f787f65..3f51c16e3c 100644 --- a/copilot/pom.xml +++ b/copilot/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT copilot diff --git a/datatype-converters/pom.xml b/datatype-converters/pom.xml index 9270f2375c..b50b168d88 100644 --- a/datatype-converters/pom.xml +++ b/datatype-converters/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/events-api/pom.xml b/events-api/pom.xml index 0035e05c34..e3d13d31b9 100644 --- a/events-api/pom.xml +++ b/events-api/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/formats-common/pom.xml b/formats-common/pom.xml index 77cbf3a4a1..74e8f50e04 100644 --- a/formats-common/pom.xml +++ b/formats-common/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.example diff --git a/function-loading/functions-api/pom.xml b/function-loading/functions-api/pom.xml index 7e22b5f2b3..f65baaae1c 100644 --- a/function-loading/functions-api/pom.xml +++ b/function-loading/functions-api/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq function-loading - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT API for defining custom user functions diff --git a/function-loading/functions-binding/pom.xml b/function-loading/functions-binding/pom.xml index 246b174825..1adbe9096a 100644 --- a/function-loading/functions-binding/pom.xml +++ b/function-loading/functions-binding/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq function-loading - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT functions-binding diff --git a/function-loading/functions-binding/src/main/java/com/orbitalhq/functions/scanner/BoundFunction.kt b/function-loading/functions-binding/src/main/java/com/orbitalhq/functions/scanner/BoundFunction.kt index 9676251359..3ff570aea6 100644 --- a/function-loading/functions-binding/src/main/java/com/orbitalhq/functions/scanner/BoundFunction.kt +++ b/function-loading/functions-binding/src/main/java/com/orbitalhq/functions/scanner/BoundFunction.kt @@ -44,7 +44,7 @@ class BoundFunction( override val functionName: QualifiedName = QualifiedName(namespace, name) - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/function-loading/functions-kotlin-scripting-api/pom.xml b/function-loading/functions-kotlin-scripting-api/pom.xml index 85531b28f6..249b9438ae 100644 --- a/function-loading/functions-kotlin-scripting-api/pom.xml +++ b/function-loading/functions-kotlin-scripting-api/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq function-loading - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT functions-kotlin-scripting-api diff --git a/function-loading/pom.xml b/function-loading/pom.xml index 99429ad74e..0db389dd4d 100644 --- a/function-loading/pom.xml +++ b/function-loading/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT function-loading diff --git a/function-loading/test-java-project/pom.xml b/function-loading/test-java-project/pom.xml index 2079301f06..9286989f18 100644 --- a/function-loading/test-java-project/pom.xml +++ b/function-loading/test-java-project/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq function-loading - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT test-java-project diff --git a/history-persistence/pom.xml b/history-persistence/pom.xml index aa216e5d5c..9de8034349 100644 --- a/history-persistence/pom.xml +++ b/history-persistence/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT history-persistence @@ -45,7 +45,7 @@ com.orbitalhq vyne-spring - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT io.projectreactor diff --git a/history-service/pom.xml b/history-service/pom.xml index 142df05dda..1dac31dd0d 100644 --- a/history-service/pom.xml +++ b/history-service/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT history-service @@ -37,12 +37,12 @@ com.orbitalhq history-persistence - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.orbitalhq vyne-history-core - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.springframework.security diff --git a/licensing/license-api/pom.xml b/licensing/license-api/pom.xml index 684ac46172..89fc4a0a7a 100644 --- a/licensing/license-api/pom.xml +++ b/licensing/license-api/pom.xml @@ -5,7 +5,7 @@ licensing com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/licensing/license-client/pom.xml b/licensing/license-client/pom.xml index a839f99c2a..a76f34ecf0 100644 --- a/licensing/license-client/pom.xml +++ b/licensing/license-client/pom.xml @@ -5,7 +5,7 @@ licensing com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/licensing/pom.xml b/licensing/pom.xml index c3c6a36eb6..12678949dd 100644 --- a/licensing/pom.xml +++ b/licensing/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/metrics-utils/pom.xml b/metrics-utils/pom.xml index 97527f3bba..b093f7ea21 100644 --- a/metrics-utils/pom.xml +++ b/metrics-utils/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT metrics-utils diff --git a/monitoring-common/pom.xml b/monitoring-common/pom.xml index e66f8ca21d..083a58db69 100644 --- a/monitoring-common/pom.xml +++ b/monitoring-common/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT monitoring-common diff --git a/nebula-support/pom.xml b/nebula-support/pom.xml index 547f051c2e..dcc7c33b78 100644 --- a/nebula-support/pom.xml +++ b/nebula-support/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT nebula-support diff --git a/orbital-taxi-publisher/pom.xml b/orbital-taxi-publisher/pom.xml index f4d5076ec7..ec7dee0519 100644 --- a/orbital-taxi-publisher/pom.xml +++ b/orbital-taxi-publisher/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT orbital-taxi-publisher diff --git a/persistence-utils/pom.xml b/persistence-utils/pom.xml index 1120195125..c3f6535d6d 100644 --- a/persistence-utils/pom.xml +++ b/persistence-utils/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT persistence-utils diff --git a/pipelines/pipeline-jet-api/pom.xml b/pipelines/pipeline-jet-api/pom.xml index f78e160f78..d9c5487cfa 100644 --- a/pipelines/pipeline-jet-api/pom.xml +++ b/pipelines/pipeline-jet-api/pom.xml @@ -5,7 +5,7 @@ pipelines com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/pipelines/pipeline-jet/pom.xml b/pipelines/pipeline-jet/pom.xml index 7cd588498e..105d75ecd6 100644 --- a/pipelines/pipeline-jet/pom.xml +++ b/pipelines/pipeline-jet/pom.xml @@ -5,7 +5,7 @@ pipelines com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -217,7 +217,7 @@ com.orbitalhq schema-server-core - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT test diff --git a/pipelines/pom.xml b/pipelines/pom.xml index 0af16fe3cf..e11967be0f 100644 --- a/pipelines/pom.xml +++ b/pipelines/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/pipelines/stream-engine/pom.xml b/pipelines/stream-engine/pom.xml index 1fbcd6d572..2d9c05851e 100644 --- a/pipelines/stream-engine/pom.xml +++ b/pipelines/stream-engine/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq pipelines - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT stream-engine @@ -212,7 +212,7 @@ com.orbitalhq schema-server-core - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT test diff --git a/pipelines/stream-engine/src/main/java/com/orbitalhq/pipelines/jet/streams/ResultStreamAuthorizationDecorator.kt b/pipelines/stream-engine/src/main/java/com/orbitalhq/pipelines/jet/streams/ResultStreamAuthorizationDecorator.kt index 8f437928f8..56aee224cf 100644 --- a/pipelines/stream-engine/src/main/java/com/orbitalhq/pipelines/jet/streams/ResultStreamAuthorizationDecorator.kt +++ b/pipelines/stream-engine/src/main/java/com/orbitalhq/pipelines/jet/streams/ResultStreamAuthorizationDecorator.kt @@ -9,6 +9,7 @@ import com.orbitalhq.models.TypedInstance import com.orbitalhq.query.policyManager.ExecutionScope import com.orbitalhq.query.policyManager.PolicyEvaluator import com.orbitalhq.schemas.Schema +import kotlinx.coroutines.reactor.mono import lang.taxi.policies.PolicyOperationScope import lang.taxi.services.OperationScope import org.springframework.security.core.Authentication @@ -44,13 +45,18 @@ class ResultStreamAuthorizationDecorator( val queryReturnType = querySchema.type(query.returnType) val instanceType = queryReturnType.collectionType ?: queryReturnType - return stream.mapNotNull { value -> - // first, parse back to a typed instance - val valueAsTypedInstance = TypedInstance.from(instanceType, value, querySchema, source = Provided) - val evaluatedTypedInstance = policyEvaluator.evaluate(valueAsTypedInstance, queryContext, executionScope) - // Convert back to a raw object, since that's what we started with - evaluatedTypedInstance.toRawObject() - } + return stream + .flatMap { value -> + val valueAsTypedInstance = + TypedInstance.from(instanceType, value, querySchema, source = Provided) + + mono { + val evaluatedTypedInstance = + policyEvaluator.evaluate(valueAsTypedInstance, queryContext, executionScope) + // Convert back to a raw object, since that's what we started with + evaluatedTypedInstance.toRawObject() + } + } } fun applyPolicies(stream: Flux, streamName: String, principal: Authentication, schema: Schema): Flux { return applyPolicies(stream, streamName, principal.toVyneUser(), schema) diff --git a/plugin-api/pom.xml b/plugin-api/pom.xml index 281a95dd35..65d0479de3 100644 --- a/plugin-api/pom.xml +++ b/plugin-api/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT plugin-api diff --git a/plugin-loader/pom.xml b/plugin-loader/pom.xml index abb83dc207..770f4421a9 100644 --- a/plugin-loader/pom.xml +++ b/plugin-loader/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT plugin-loader diff --git a/policy-evaluator/pom.xml b/policy-evaluator/pom.xml index 52423008c9..d09a22a17e 100644 --- a/policy-evaluator/pom.xml +++ b/policy-evaluator/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.example diff --git a/pom.xml b/pom.xml index 21c1983618..2a5d3fcfe7 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.orbitalhq platform pom - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.springframework.boot diff --git a/protobuf-utils/pom.xml b/protobuf-utils/pom.xml index 417e1e3983..fa17f40224 100644 --- a/protobuf-utils/pom.xml +++ b/protobuf-utils/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/query-node-api/pom.xml b/query-node-api/pom.xml index a3184bad9a..ab0d1667df 100644 --- a/query-node-api/pom.xml +++ b/query-node-api/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT query-node-api diff --git a/query-node-core/pom.xml b/query-node-core/pom.xml index 7d785441fa..ac6950f453 100644 --- a/query-node-core/pom.xml +++ b/query-node-core/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT query-node-core @@ -197,7 +197,7 @@ com.orbitalhq vyne-spring-http - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.orbitalhq diff --git a/query-node-native/pom.xml b/query-node-native/pom.xml index d04760dbf6..9b77fbdb12 100644 --- a/query-node-native/pom.xml +++ b/query-node-native/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT query-node-native diff --git a/query-node-service/pom.xml b/query-node-service/pom.xml index 26d7612251..328cd29395 100644 --- a/query-node-service/pom.xml +++ b/query-node-service/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT query-node-service diff --git a/schema-management/pom.xml b/schema-management/pom.xml index 12fba01f2e..5f651ea954 100644 --- a/schema-management/pom.xml +++ b/schema-management/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/schema-management/schema-api/pom.xml b/schema-management/schema-api/pom.xml index ed750830c1..d0a72bf2ca 100644 --- a/schema-management/schema-api/pom.xml +++ b/schema-management/schema-api/pom.xml @@ -5,7 +5,7 @@ schema-management com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/schema-management/schema-consumer-api/pom.xml b/schema-management/schema-consumer-api/pom.xml index ffcb7f55d7..6f2bb05ee7 100644 --- a/schema-management/schema-consumer-api/pom.xml +++ b/schema-management/schema-consumer-api/pom.xml @@ -5,7 +5,7 @@ schema-management com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -21,12 +21,12 @@ com.orbitalhq schema-api - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.orbitalhq events-api - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.orbitalhq diff --git a/schema-management/schema-http-common/pom.xml b/schema-management/schema-http-common/pom.xml index 322adf29a4..2589d04719 100644 --- a/schema-management/schema-http-common/pom.xml +++ b/schema-management/schema-http-common/pom.xml @@ -5,7 +5,7 @@ schema-management com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/schema-management/schema-http-consumer/pom.xml b/schema-management/schema-http-consumer/pom.xml index 7286458435..3b5eb7fd0f 100644 --- a/schema-management/schema-http-consumer/pom.xml +++ b/schema-management/schema-http-consumer/pom.xml @@ -5,7 +5,7 @@ schema-management com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -20,17 +20,17 @@ com.orbitalhq schema-http-common - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.orbitalhq schema-consumer-api - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.orbitalhq events-api - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT diff --git a/schema-management/schema-http-publisher/pom.xml b/schema-management/schema-http-publisher/pom.xml index abb5195136..d05e6cbab6 100644 --- a/schema-management/schema-http-publisher/pom.xml +++ b/schema-management/schema-http-publisher/pom.xml @@ -5,7 +5,7 @@ schema-management com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -20,12 +20,12 @@ com.orbitalhq schema-http-common - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.orbitalhq schema-publisher-api - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.springframework.retry diff --git a/schema-management/schema-publisher-api/pom.xml b/schema-management/schema-publisher-api/pom.xml index 494fc6be95..b592b3f806 100644 --- a/schema-management/schema-publisher-api/pom.xml +++ b/schema-management/schema-publisher-api/pom.xml @@ -5,7 +5,7 @@ schema-management com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -20,7 +20,7 @@ com.orbitalhq schema-api - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.taxilang diff --git a/schema-management/schema-publisher-cli/pom.xml b/schema-management/schema-publisher-cli/pom.xml index a23fd093d6..396005b848 100644 --- a/schema-management/schema-publisher-cli/pom.xml +++ b/schema-management/schema-publisher-cli/pom.xml @@ -5,7 +5,7 @@ schema-management com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -28,7 +28,7 @@ com.orbitalhq schema-http-publisher - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.github.ajalt.clikt diff --git a/schema-management/schema-publisher-spring-boot-starter/pom.xml b/schema-management/schema-publisher-spring-boot-starter/pom.xml index f2d1cbe528..390f774ee9 100644 --- a/schema-management/schema-publisher-spring-boot-starter/pom.xml +++ b/schema-management/schema-publisher-spring-boot-starter/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq schema-management - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT schema-publisher-spring-boot-starter diff --git a/schema-management/schema-rsocket-common/pom.xml b/schema-management/schema-rsocket-common/pom.xml index d2fbc50056..9f0506d5a9 100644 --- a/schema-management/schema-rsocket-common/pom.xml +++ b/schema-management/schema-rsocket-common/pom.xml @@ -5,7 +5,7 @@ schema-management com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -22,7 +22,7 @@ com.orbitalhq schema-api - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT diff --git a/schema-management/schema-spring/pom.xml b/schema-management/schema-spring/pom.xml index 7a4d1d1e8f..3fc8273c0e 100644 --- a/schema-management/schema-spring/pom.xml +++ b/schema-management/schema-spring/pom.xml @@ -5,7 +5,7 @@ schema-management com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -46,7 +46,7 @@ com.orbitalhq schema-publisher-api - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.taxilang @@ -56,12 +56,12 @@ com.orbitalhq schema-rsocket-publisher - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.orbitalhq schema-rsocket-consumer - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.springframework.boot @@ -70,17 +70,17 @@ com.orbitalhq schema-rsocket-common - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.orbitalhq schema-http-publisher - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT com.orbitalhq schema-http-consumer - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT org.springframework diff --git a/schema-server-api/pom.xml b/schema-server-api/pom.xml index 1ed30f2fc0..a4aa6b6a66 100644 --- a/schema-server-api/pom.xml +++ b/schema-server-api/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/schema-server-core/pom.xml b/schema-server-core/pom.xml index 86dcd098cf..236c8e3d64 100644 --- a/schema-server-core/pom.xml +++ b/schema-server-core/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/schema-server/pom.xml b/schema-server/pom.xml index 27e60335e9..aa86f41a83 100644 --- a/schema-server/pom.xml +++ b/schema-server/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/schema-store-client/pom.xml b/schema-store-client/pom.xml index bea1efe04c..22d14ea48c 100644 --- a/schema-store-client/pom.xml +++ b/schema-store-client/pom.xml @@ -3,7 +3,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/spring-utils/pom.xml b/spring-utils/pom.xml index 13759fea03..f434df5cb1 100644 --- a/spring-utils/pom.xml +++ b/spring-utils/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT spring-utils diff --git a/station/pom.xml b/station/pom.xml index 9369e2e1bd..d52054b013 100644 --- a/station/pom.xml +++ b/station/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/taxi-playground-core/pom.xml b/taxi-playground-core/pom.xml index 86d7dc06ad..e76b4bc5fb 100644 --- a/taxi-playground-core/pom.xml +++ b/taxi-playground-core/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT taxi-playground-core diff --git a/taxi-playground/pom.xml b/taxi-playground/pom.xml index 5ffcc15f7d..9bc4f9bbde 100644 --- a/taxi-playground/pom.xml +++ b/taxi-playground/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/taxiql-query-engine/pom.xml b/taxiql-query-engine/pom.xml index d0e2689b73..3b02ff0d09 100644 --- a/taxiql-query-engine/pom.xml +++ b/taxiql-query-engine/pom.xml @@ -4,7 +4,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -191,7 +191,7 @@ Do not allow this to leak beyond a test scope com.orbitalhq vyne-spring-http - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT test diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/Vyne.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/Vyne.kt index c4d0628e08..2ba9a119ca 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/Vyne.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/Vyne.kt @@ -230,7 +230,7 @@ class Vyne( } @VisibleForTesting - internal fun buildContextAndExpression( + internal suspend fun buildContextAndExpression( taxiQl: TaxiQlQuery, queryId: String, clientQueryId: String?, @@ -277,7 +277,7 @@ class Vyne( ) } - private fun convertTaxiQlFactToInstances( + private suspend fun convertTaxiQlFactToInstances( taxiQl: TaxiQlQuery, arguments: Map, executionContextFacts: Set = emptySet() @@ -318,23 +318,23 @@ class Vyne( .filter { it.value is FactValue.Expression } .fold(constants) { previousParams, parameter -> val facts = CopyOnWriteFactBag(emptyList(), schema, previousParams) - val valueSupplier = FactBagValueSupplier(facts, schema) - val accessorReader = AccessorReader( - valueSupplier, - schema.functionRegistry, - schema - ) + val valueSupplier = FactBagValueSupplier(facts, schema) + val accessorReader = AccessorReader( + valueSupplier, + schema.functionRegistry, + schema + ) - val expression = parameter.value as FactValue.Expression - val evaluationResult = accessorReader.evaluate( - value = facts, - returnType = schema.type(parameter.type), - expression = expression.expression, - format = null, - dataSource = Provided - ) + val expression = parameter.value as FactValue.Expression + val evaluationResult = accessorReader.evaluate( + value = facts, + returnType = schema.type(parameter.type), + expression = expression.expression, + format = null, + dataSource = Provided + ) previousParams + ScopedFact(ProjectionFunctionScope(parameter.name, parameter.type), evaluationResult) - } + } return evaluatedExpressions.map { it.scope.name to it.fact } .toMap() @@ -411,7 +411,7 @@ class Vyne( } @Deprecated("Looks like this is only called in tests. Does not propogate trace contexts. If this gets used, then it needs to accept a traceContext (or similar)") - fun evaluate(taxiExpression: String, returnType: Type): TypedInstance { + suspend fun evaluate(taxiExpression: String, returnType: Type): TypedInstance { val (schemaWithType, expressionType) = this.schema.compileExpression(taxiExpression, returnType) val queryContext = queryEngine(schema = schemaWithType) @@ -424,13 +424,13 @@ class Vyne( // That's wrong, as generally the collection will be the input, especially if our predciate / expression // is a contains(...) val buildResult = TypedObjectFactory( - expressionType, - queryContext.facts, - schemaWithType, - source = Provided, - inPlaceQueryEngine = queryContext, - functionResultCache = queryContext.functionResultCache - ).build() + expressionType, + queryContext.facts, + schemaWithType, + source = Provided, + inPlaceQueryEngine = queryContext, + functionResultCache = queryContext.functionResultCache + ).build() return buildResult } diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/DirectServiceInvocationStrategy.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/DirectServiceInvocationStrategy.kt index e02c7453a5..4f18de9ea5 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/DirectServiceInvocationStrategy.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/DirectServiceInvocationStrategy.kt @@ -68,7 +68,7 @@ class DirectServiceInvocationStrategy(invocationService: OperationInvocationServ return invokeOperations(operations, context, target) } - private fun lookForCandidateServices( + private suspend fun lookForCandidateServices( context: QueryContext, target: Set ): Map>> { @@ -84,13 +84,16 @@ class DirectServiceInvocationStrategy(invocationService: OperationInvocationServ /** * Returns the operations that we can invoke, grouped by target query node. */ - private fun getCandidateOperations( + private suspend fun getCandidateOperations( schema: Schema, target: Set, context: QueryContext ): Map>> { - val grouped = target.map { it to getCandidateOperations(schema, it, context) } - .groupBy({ it.first }, { it.second }) + val grouped = mutableMapOf>>>() + for (item in target) { + val candidates = getCandidateOperations(schema, item, context) + grouped.getOrPut(item) { mutableListOf() }.add(candidates) + } val result = grouped.mapValues { (_, operationParameterMaps) -> operationParameterMaps.reduce { acc, map -> acc + map } @@ -103,7 +106,7 @@ class DirectServiceInvocationStrategy(invocationService: OperationInvocationServ * (either because they have no parameters, or because all their parameters are populated by constraints) * and the set of parameters that we have identified values for */ - private fun getCandidateOperations( + private suspend fun getCandidateOperations( schema: Schema, target: QuerySpecTypeNode, context: QueryContext @@ -114,34 +117,28 @@ class DirectServiceInvocationStrategy(invocationService: OperationInvocationServ it.returnType.isAssignableTo(target.type) && it.operationType == OperationScope.READ_ONLY } } - val operations = operationsForType - .mapNotNull { operation -> - val (satisfiesConstraints, operationParameters) = compareOperationContractToDataRequirementsAndFetchSearchParams( - operation, - target, - schema, - context - ) - if (!satisfiesConstraints) { - null - } else { - operation to operationParameters - } - } - .map { (operation, parameters) -> - populateParamsFromContextValues(operation, parameters, context) - } - .map { (operation, parameters) -> - provideUnpopulatedParametersWithDefaults(operation, parameters, context) + val result = mutableMapOf>() + for (operation in operationsForType) { + val (satisfiesConstraints, operationParameters) = compareOperationContractToDataRequirementsAndFetchSearchParams( + operation, + target, + schema, + context + ) + if (!satisfiesConstraints) continue + + val (op1, params1) = populateParamsFromContextValues(operation, operationParameters, context) + val (op2, params2) = provideUnpopulatedParametersWithDefaults(op1, params1, context) + + // Check to see if there are any outstanding parameters that haven't been populated + val unpopulatedParams = op2.parameters.filter { parameter -> + !params2.containsKey(parameter) && !parameter.nullable } - .filter { (operation, populatedOperationParameters) -> - // Check to see if there are any outstanding parameters that haven't been populated - val unpopulatedParams = operation.parameters.filter { parameter -> - !populatedOperationParameters.containsKey(parameter) && !parameter.nullable - } - unpopulatedParams.isEmpty() + if (unpopulatedParams.isEmpty()) { + result[op2] = params2 } - return operations.toMap() + } + return result } /** @@ -166,7 +163,7 @@ class DirectServiceInvocationStrategy(invocationService: OperationInvocationServ * Adds any parameters that are so far unpopulated, but * have a default expression that can be used to populate them */ - private fun provideUnpopulatedParametersWithDefaults( + private suspend fun provideUnpopulatedParametersWithDefaults( operation: RemoteOperation, parameters: Map, context: QueryContext @@ -176,7 +173,7 @@ class DirectServiceInvocationStrategy(invocationService: OperationInvocationServ .filter { !parameters.containsKey(it) } .associateWith { parameter -> context.evaluate(parameter.defaultValue!!) - } + } return operation to (parameters + defaultValues) } @@ -185,7 +182,7 @@ class DirectServiceInvocationStrategy(invocationService: OperationInvocationServ * If a contract exists on the target which provides input params, and the operation * can satisfy the contract, then the parameters to search inputs are returned mapped. */ - private fun compareOperationContractToDataRequirementsAndFetchSearchParams( + private suspend fun compareOperationContractToDataRequirementsAndFetchSearchParams( remoteOperation: RemoteOperation, target: QuerySpecTypeNode, schema: Schema, @@ -224,19 +221,20 @@ class DirectServiceInvocationStrategy(invocationService: OperationInvocationServ return allOperationConstraintsSatisfied to operationConstraintParameterValues } - private fun getProvidedParameterValues( + private suspend fun getProvidedParameterValues( remoteOperation: Operation, providedValues: List>, context: QueryContext, schema: Schema ): List> { - return providedValues.mapNotNull { (paramExpression, providedValueExpression) -> + val result = mutableListOf>() + for ((paramExpression, providedValueExpression) in providedValues) { when (paramExpression) { is ArgumentSelector -> { val parameter = remoteOperation.parameter(paramExpression.scopeWithPath) if (parameter == null) { logger.warn { "An expression was found to provide a value for parameter ${paramExpression.path}, but no such parameter exists on operation ${remoteOperation.name}" } - return@mapNotNull null + continue } // Short circut - if it's a literal (which is the most common case), then // provide the value @@ -250,15 +248,15 @@ class DirectServiceInvocationStrategy(invocationService: OperationInvocationServ else -> context.evaluate(expression = providedValueExpression) } - parameter to expressionResult + result.add(parameter to expressionResult) } else -> { logger.warn { "Not implemented: Mapping parameterExpression of type ${paramExpression::class.simpleName}" } - null } } } + return result } } diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/ObjectBuilder.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/ObjectBuilder.kt index 14cdf31b7a..1d43365be6 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/ObjectBuilder.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/ObjectBuilder.kt @@ -192,7 +192,7 @@ class ObjectBuilder( } } - private fun evaluateExpressionType(targetType: Type): TypedInstance { + private suspend fun evaluateExpressionType(targetType: Type): TypedInstance { return TypedObjectFactory( targetType, // Note: This used to be an empty list, @@ -232,7 +232,7 @@ class ObjectBuilder( * items: Thing[] by [ThingToIterate[] with { CustomerName }] * }[] */ - private fun buildCollectionWithProjectionExpression(targetType: Type): TypedInstance { + private suspend fun buildCollectionWithProjectionExpression(targetType: Type): TypedInstance { val collectionProjectionBuilder = accessorReaders.filterIsInstance().firstOrNull() ?: error("No CollectionProjectionBuilder was present in the acessor readers") return collectionProjectionBuilder.process( diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/QueryContext.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/QueryContext.kt index 64781cd6bf..3e0c01a06f 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/QueryContext.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/QueryContext.kt @@ -596,7 +596,7 @@ data class QueryContext( } - override fun evaluate(expression: Expression, facts: FactBag, source: DataSource): TypedInstance { + override suspend fun evaluate(expression: Expression, facts: FactBag, source: DataSource): TypedInstance { return TypedObjectFactory( schema.type(expression.returnType), facts.withAdditionalScopedFacts(this.scopedFacts, schema), @@ -607,7 +607,7 @@ data class QueryContext( ).evaluateExpression(expression) } - override fun evaluate(expression: Expression, value: TypedInstance, source: DataSource): TypedInstance { + override suspend fun evaluate(expression: Expression, value: TypedInstance, source: DataSource): TypedInstance { return TypedObjectFactory( schema.type(expression.returnType), value, diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/QueryOperationInvocationStrategy.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/QueryOperationInvocationStrategy.kt index 91293d9a20..5b9244a608 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/QueryOperationInvocationStrategy.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/QueryOperationInvocationStrategy.kt @@ -51,7 +51,7 @@ class QueryOperationInvocationStrategy( return result } - private fun lookForCandidateQueryOperations( + private suspend fun lookForCandidateQueryOperations( context: QueryContext, target: Set ): Map>> { @@ -61,7 +61,7 @@ class QueryOperationInvocationStrategy( } @VisibleForTesting - internal fun lookForCandidateQueryOperations( + internal suspend fun lookForCandidateQueryOperations( schema: Schema, target: QuerySpecTypeNode, context: QueryContext @@ -75,7 +75,7 @@ class QueryOperationInvocationStrategy( .filter { it.returnType.isAssignableTo(target.type) } .filter { it.hasFilterCapability } - return queryOperations.filter { + val filtered = queryOperations.filter { queryServiceSatisfiesConstraints( schema, it, @@ -84,15 +84,16 @@ class QueryOperationInvocationStrategy( ) } .mapNotNull { queryOperation -> findGrammarBuilder(queryOperation) } - .map { (queryOperation, grammarBuilder) -> - val queryTarget = if (isCovariance(queryOperation.returnType, target.type)) { - target.copy(type = queryOperation.returnType) - } else target - queryOperation to grammarBuilder.buildQuery(queryTarget, queryOperation, schema, context) + val result = mutableMapOf>() + for ((queryOperation, grammarBuilder) in filtered) { + val queryTarget = if (isCovariance(queryOperation.returnType, target.type)) { + target.copy(type = queryOperation.returnType) + } else target - } - .toList().toMap() + result[queryOperation] = grammarBuilder.buildQuery(queryTarget, queryOperation, schema, context) + } + return result } // TODO : We shouldn't be doing this kind of covariance checking here - these filters diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/collections/CollectionProjectionBuilder.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/collections/CollectionProjectionBuilder.kt index 68c7b0883f..ac0b693136 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/collections/CollectionProjectionBuilder.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/collections/CollectionProjectionBuilder.kt @@ -10,7 +10,6 @@ import com.orbitalhq.schemas.taxi.toVyneType import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.flatMapConcat import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.runBlocking import lang.taxi.accessors.CollectionProjectionExpressionAccessor import lang.taxi.types.Arrays import kotlin.reflect.KClass @@ -29,7 +28,7 @@ class CollectionProjectionBuilder(val queryContext: QueryContext) : override val accessorType: KClass = CollectionProjectionExpressionAccessor::class - override fun process( + override suspend fun process( accessor: CollectionProjectionExpressionAccessor, objectFactory: EvaluationValueSupplier, schema: Schema, @@ -56,13 +55,11 @@ class CollectionProjectionBuilder(val queryContext: QueryContext) : } ?: emptyList() val targetMemberType = targetType.collectionType ?: targetType - val buildResults = runBlocking { - collectionToIterate.asFlow() - .flatMapConcat { collectionMember -> - queryContext.only(listOf(collectionMember) + additionalScopeFacts) - .build(TypeQueryExpression(targetMemberType)).results - }.toList() - } + val buildResults = collectionToIterate.asFlow() + .flatMapConcat { collectionMember -> + queryContext.only(listOf(collectionMember) + additionalScopeFacts) + .build(TypeQueryExpression(targetMemberType)).results + }.toList() val builtCollection = TypedCollection.from(buildResults, source) return builtCollection diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/graph/edges/ParameterFactory.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/graph/edges/ParameterFactory.kt index 0b6862c8ff..63c91d721a 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/graph/edges/ParameterFactory.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/graph/edges/ParameterFactory.kt @@ -29,7 +29,6 @@ import com.orbitalhq.utils.log import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.firstOrNull -import kotlinx.coroutines.runBlocking import lang.taxi.expressions.Expression import lang.taxi.services.operations.constraints.Constraint import lang.taxi.types.PrimitiveType @@ -119,33 +118,27 @@ class ParameterFactory { // } // experiment: Are there any collections in the context we can iterate? - val builtFromCollection = context.facts.filter { it.type.isCollection } - .asSequence() - .mapNotNull { collection: TypedInstance -> - require(collection is TypedCollection) { "Expected to recieve a TypedCollection" } - var exceptionThrown = false - val built = collection - .takeWhile { !exceptionThrown } - .mapNotNull { member -> - runBlocking { - try { - val memberOnlyQueryContext = context.only(member) - val builtFromMember = - attemptToConstruct(paramType.collectionType!!, memberOnlyQueryContext, operation, member) - builtFromMember - } catch (e: UnresolvedOperationParametersException) { - exceptionThrown = true - null - } - } - } - if (exceptionThrown) { - null - } else { - built + var builtFromCollection: List? = null + for (collection in context.facts.filter { it.type.isCollection }) { + require(collection is TypedCollection) { "Expected to recieve a TypedCollection" } + var exceptionThrown = false + val built = mutableListOf() + for (member in collection) { + if (exceptionThrown) break + try { + val memberOnlyQueryContext = context.only(member) + val builtFromMember = + attemptToConstruct(paramType.collectionType!!, memberOnlyQueryContext, operation, member) + built.add(builtFromMember) + } catch (e: UnresolvedOperationParametersException) { + exceptionThrown = true } } - .firstOrNull() + if (!exceptionThrown) { + builtFromCollection = built + break + } + } if (builtFromCollection != null) { return TypedCollection.from(builtFromCollection, MixedSources) } else { diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/policyManager/PolicyAwareOperationInvocationServiceDecorator.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/policyManager/PolicyAwareOperationInvocationServiceDecorator.kt index 32e1dc841d..8f8e17e079 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/policyManager/PolicyAwareOperationInvocationServiceDecorator.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/policyManager/PolicyAwareOperationInvocationServiceDecorator.kt @@ -43,7 +43,7 @@ class PolicyAwareOperationInvocationServiceDecorator(private val operationServic } - private fun applyPolicyInstruction( + private suspend fun applyPolicyInstruction( value: TypedInstance, context: QueryContext, executionScope: ExecutionScope diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/policyManager/PolicyEvaluator.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/policyManager/PolicyEvaluator.kt index bb97eb124c..022ddfa55b 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/policyManager/PolicyEvaluator.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/policyManager/PolicyEvaluator.kt @@ -47,7 +47,7 @@ class PolicyEvaluator { private val logger = KotlinLogging.logger {} } - fun evaluate(instance: TypedInstance, context: QueryContext, operationScope: ExecutionScope): TypedInstance { + suspend fun evaluate(instance: TypedInstance, context: QueryContext, operationScope: ExecutionScope): TypedInstance { val schema = context.schema val policyType = getPolicyType(instance, context) val policies = findPolicies(schema, policyType) @@ -60,7 +60,7 @@ class PolicyEvaluator { return evaluationResult } - private fun evaluate( + private suspend fun evaluate( applicablePolicies: List, instance: TypedInstance, context: QueryContext, @@ -111,7 +111,7 @@ class PolicyEvaluator { } } - private fun evaluatePolicyAtPath( + private suspend fun evaluatePolicyAtPath( policyWithPath: PolicyWithPath, rootInstance: TypedInstance, context: QueryContext, @@ -136,7 +136,7 @@ class PolicyEvaluator { } } - private fun evaluatePolicy( + private suspend fun evaluatePolicy( policy: Policy, rule: PolicyRule, instance: TypedInstance, diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/projection/LocalProjectionProvider.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/projection/LocalProjectionProvider.kt index d1ca56acf1..a20434fb58 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/projection/LocalProjectionProvider.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/projection/LocalProjectionProvider.kt @@ -294,7 +294,7 @@ class LocalProjectionProvider : ProjectionProvider { * * This code returns the actual fact, selecting the value from the inbound value. */ - private fun buildScopedProjectionFacts( + private suspend fun buildScopedProjectionFacts( projection: Projection, emittedResult: TypedInstance, context: QueryContext diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/queryBuilders/QueryGrammarQueryBuilder.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/queryBuilders/QueryGrammarQueryBuilder.kt index bf965d02f0..439dd84f84 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/queryBuilders/QueryGrammarQueryBuilder.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/queryBuilders/QueryGrammarQueryBuilder.kt @@ -23,7 +23,7 @@ interface QueryGrammarQueryBuilder { return this.supportedGrammars.contains(grammar) } - fun buildQuery( + suspend fun buildQuery( spec: QuerySpecTypeNode, queryOperation: QueryOperation, schema: Schema, diff --git a/taxiql-query-engine/src/main/java/com/orbitalhq/query/queryBuilders/TaxiQlGrammarQueryBuilder.kt b/taxiql-query-engine/src/main/java/com/orbitalhq/query/queryBuilders/TaxiQlGrammarQueryBuilder.kt index 70b80fead8..1154c75127 100644 --- a/taxiql-query-engine/src/main/java/com/orbitalhq/query/queryBuilders/TaxiQlGrammarQueryBuilder.kt +++ b/taxiql-query-engine/src/main/java/com/orbitalhq/query/queryBuilders/TaxiQlGrammarQueryBuilder.kt @@ -39,7 +39,7 @@ private val logger = KotlinLogging.logger {} */ class TaxiQlGrammarQueryBuilder : QueryGrammarQueryBuilder { override val supportedGrammars: List = listOf(VyneQlGrammar.GRAMMAR_NAME) - override fun buildQuery( + override suspend fun buildQuery( spec: QuerySpecTypeNode, queryOperation: QueryOperation, schema: Schema, @@ -61,7 +61,7 @@ class TaxiQlGrammarQueryBuilder : QueryGrammarQueryBuilder { } @VisibleForTesting - internal fun buildTaxiQl(spec: QuerySpecTypeNode, context: QueryContext): Pair> { + internal suspend fun buildTaxiQl(spec: QuerySpecTypeNode, context: QueryContext): Pair> { val constraints = spec.dataConstraints if (constraints.size > 1) { logger.warn { "Received multiple constraints - expected a single, compound constraint. ${constraints.joinToString()}" } @@ -75,14 +75,14 @@ class TaxiQlGrammarQueryBuilder : QueryGrammarQueryBuilder { return """find { ${spec.type.name.parameterizedName}${constraintsStatement} }""" to resolvedValues } - private fun buildConstraint(constraint: Constraint, context: QueryContext): Pair> { + private suspend fun buildConstraint(constraint: Constraint, context: QueryContext): Pair> { return when (constraint) { is ExpressionConstraint -> buildExpressionConstraint(constraint, context) else -> error("Support for constraint type ${constraint::class.simpleName} not implemented yet") } } - private fun buildExpressionConstraint( + private suspend fun buildExpressionConstraint( constraint: ExpressionConstraint, context: QueryContext ): Pair> { @@ -135,7 +135,7 @@ private fun typedInstanceToLiteralExpressionAndValues( * returning a new expression where things like ArgumentSelectors have been replaced * with Literals */ -fun Expression.resolveVariablesUsing(context: QueryContext): Pair> { +suspend fun Expression.resolveVariablesUsing(context: QueryContext): Pair> { return when (this) { is OperatorExpression -> { val (lhs, lhsInstances) = lhs.resolveVariablesUsing(context) diff --git a/taxiql-query-engine/src/test/java/com/orbitalhq/TypedObjectFactoryDeadlockSpec.kt b/taxiql-query-engine/src/test/java/com/orbitalhq/TypedObjectFactoryDeadlockSpec.kt new file mode 100644 index 0000000000..969221cfc7 --- /dev/null +++ b/taxiql-query-engine/src/test/java/com/orbitalhq/TypedObjectFactoryDeadlockSpec.kt @@ -0,0 +1,118 @@ +package com.orbitalhq + +import com.orbitalhq.models.json.parseJson +import com.orbitalhq.models.json.parseJsonCollection +import io.kotest.core.spec.style.DescribeSpec +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.withTimeout + +class TypedObjectFactoryDeadlockSpec : DescribeSpec({ + + describe("A dead lock that occurred in TypedObjectFactory") { + it("should run a query designed to produce a deadlock, without producing a deadlock") { + // Constrain Default dispatcher to make deadlock reproducible + val threadCount = Runtime.getRuntime().availableProcessors() + + val (vyne, stubService) = testVyne( + """ + type TradeId inherits String + type Isin inherits String + type UnresolvableType inherits String // intentionally never provided + + model Trade { + id: TradeId + isin: Isin + } + + model EnrichedTrade { + id: TradeId + isin: Isin + mystery: UnresolvableType? // will trigger handleTypeNotFound + } + + @Datasource + service TradeService { + operation getTrades(): Trade[] + } + """.trimIndent() + ) + + // Generate enough records to saturate the Default thread pool + val trades = (1..(threadCount * 3)).map { i -> + """{ "id": "trade$i", "isin": "US00000$i" }""" + }.joinToString(",", "[", "]") + + stubService.addResponse( + "getTrades", + vyne.parseJson("Trade[]", trades) + ) + + // withTimeout will expose a deadlock that would otherwise hang the test suite forever + withTimeout(10_000) { + val result = vyne.query( + """ + find { Trade[] } as EnrichedTrade[] + """.trimIndent() + ) + result.rawObjects() // force collection, triggering concurrent object construction + } + } + + + it("should run another query designed to produce a deadlock, wihtout producing a deadlock") { + val (vyne, stubService) = testVyne( + """ + type Isin inherits String + type Ric inherits String + + model InputModel { + ric: Ric + } + + model OutputModel { + isin: Isin + } + + parameter model RicRequest { + ric: Ric + } + + model RicResponse { + isin: Isin + } + + @Datasource + service InputService { + operation getInputs(): InputModel[] + } + + service IsinLookupService { + operation lookup(@RequestBody req: RicRequest): RicResponse + } + """.trimIndent() + ) + + // Generate enough rows to exhaust the DefaultDispatcher thread pool + // The pool size is typically Runtime.availableProcessors(), so generate more than that + val rowCount = Runtime.getRuntime().availableProcessors() * 3 + + stubService.addResponse( + "getInputs", vyne.parseJsonCollection( + "InputModel[]", + (1..rowCount).joinToString(",", "[", "]") { """{"ric": "ric$it"}""" } + ) + ) + + // IsinLookupService is NOT stubbed - it will trigger handleTypeNotFound + // which calls runBlocking { findType() } + + val result = withTimeout(10_000) { + val queryResult = vyne.query("find { InputModel[] } as OutputModel[]") + queryResult.rawObjects() + } + + // If we get here without timeout, the fix works + result.size shouldBe rowCount + } + } +}) diff --git a/taxiql-query-engine/src/test/java/com/orbitalhq/models/ConditionalFieldReaderTest.kt b/taxiql-query-engine/src/test/java/com/orbitalhq/models/ConditionalFieldReaderTest.kt index d1d22afead..ae397e240f 100644 --- a/taxiql-query-engine/src/test/java/com/orbitalhq/models/ConditionalFieldReaderTest.kt +++ b/taxiql-query-engine/src/test/java/com/orbitalhq/models/ConditionalFieldReaderTest.kt @@ -123,7 +123,7 @@ type TransformedTradeRecord { } """) val json = """{ "bankDirection" : "Buy" }""" - val order = TypedObjectFactory(vyne.schema.type("Order"), json, vyne.schema, source = Provided).build() as TypedObject + val order = kotlinx.coroutines.runBlocking { TypedObjectFactory(vyne.schema.type("Order"), json, vyne.schema, source = Provided).build() } as TypedObject order["clientDirection"].value!!.should.equal("Sell") order["bankDirection"].value!!.should.equal("Buy") @@ -142,7 +142,7 @@ type TransformedTradeRecord { } """) val json = """{ "bankDirection" : "buy" }""" - val order = TypedObjectFactory(vyne.schema.type("Order"), json, vyne.schema, source = Provided).build() as TypedObject + val order = kotlinx.coroutines.runBlocking { TypedObjectFactory(vyne.schema.type("Order"), json, vyne.schema, source = Provided).build() } as TypedObject order["bankDirection"].value!!.should.equal("buy") order["clientDirection"].value.should.be.`null` @@ -162,7 +162,7 @@ type TransformedTradeRecord { } """) val json = """{ "bankDirection" : "buy" }""" - val order = TypedObjectFactory(vyne.schema.type("Order"), json, vyne.schema, source = Provided).build() as TypedObject + val order = kotlinx.coroutines.runBlocking { TypedObjectFactory(vyne.schema.type("Order"), json, vyne.schema, source = Provided).build() } as TypedObject order["bankDirection"].value!!.should.equal("buy") order["clientDirection"].value.should.equal("Sell") diff --git a/taxiql-query-engine/src/test/java/com/orbitalhq/models/functions/stdlib/StringsTest.kt b/taxiql-query-engine/src/test/java/com/orbitalhq/models/functions/stdlib/StringsTest.kt index a56c8e91ff..a52d994853 100644 --- a/taxiql-query-engine/src/test/java/com/orbitalhq/models/functions/stdlib/StringsTest.kt +++ b/taxiql-query-engine/src/test/java/com/orbitalhq/models/functions/stdlib/StringsTest.kt @@ -207,9 +207,9 @@ class StringsTest { val endArg = 4.toTypedValue(intType) val nullArg = TypedNull.create(stringType) - Mid.invoke(listOf(nullArg, startArg, endArg), schema, stringType, stubAccessor, mock { },null).value.should.be.`null` - Mid.invoke(listOf(helloArg, nullArg, endArg), schema, stringType, stubAccessor, mock { },null).value.should.be.`null` - Mid.invoke(listOf(helloArg, startArg, nullArg), schema, stringType, stubAccessor, mock { },null).value.should.be.`null` + kotlinx.coroutines.runBlocking { Mid.invoke(listOf(nullArg, startArg, endArg), schema, stringType, stubAccessor, mock { },null) }.value.should.be.`null` + kotlinx.coroutines.runBlocking { Mid.invoke(listOf(helloArg, nullArg, endArg), schema, stringType, stubAccessor, mock { },null) }.value.should.be.`null` + kotlinx.coroutines.runBlocking { Mid.invoke(listOf(helloArg, startArg, nullArg), schema, stringType, stubAccessor, mock { },null) }.value.should.be.`null` } @Test diff --git a/taxiql-query-engine/src/test/java/com/orbitalhq/query/QueryOperationInvocationStrategyTest.kt b/taxiql-query-engine/src/test/java/com/orbitalhq/query/QueryOperationInvocationStrategyTest.kt index 3b96c78293..8a12804b57 100644 --- a/taxiql-query-engine/src/test/java/com/orbitalhq/query/QueryOperationInvocationStrategyTest.kt +++ b/taxiql-query-engine/src/test/java/com/orbitalhq/query/QueryOperationInvocationStrategyTest.kt @@ -42,14 +42,14 @@ class QueryOperationInvocationStrategyTest { @Test fun matchesQueryOperationForFindAll() { val (context,querySpecNode) = getQuerySpecNode("find { Person[] }", schema) - val candidates = queryOperationStrategy.lookForCandidateQueryOperations(schema, querySpecNode, context) + val candidates = kotlinx.coroutines.runBlocking { queryOperationStrategy.lookForCandidateQueryOperations(schema, querySpecNode, context) } candidates.should.have.size(1) } @Test fun matchesQueryOperationFilteringEqualsAttributeName() { val (context,querySpecNode) = getQuerySpecNode("find { Person[]( FirstName == 'Jimmy' ) }", schema) - val candidates = queryOperationStrategy.lookForCandidateQueryOperations(schema, querySpecNode, context) + val candidates = kotlinx.coroutines.runBlocking { queryOperationStrategy.lookForCandidateQueryOperations(schema, querySpecNode, context) } candidates.should.have.size(1) } @@ -75,7 +75,7 @@ class QueryOperationInvocationStrategyTest { """.trimIndent() ) val (context,querySpecNode) = getQuerySpecNode("find { Trade[]( TraderName == 'Jimmy' ) }", schema) - val candidates = queryOperationStrategy.lookForCandidateQueryOperations(schema, querySpecNode, context) + val candidates = kotlinx.coroutines.runBlocking { queryOperationStrategy.lookForCandidateQueryOperations(schema, querySpecNode, context) } candidates.should.have.size(2) } @@ -109,7 +109,7 @@ class QueryOperationInvocationStrategyTest { """.trimIndent() ) val (context,querySpecNode) = getQuerySpecNode("find { Trade[]( TraderName == 'Jimmy' ) }", schema) - val candidates = queryOperationStrategy.lookForCandidateQueryOperations(schema, querySpecNode, context) + val candidates = kotlinx.coroutines.runBlocking { queryOperationStrategy.lookForCandidateQueryOperations(schema, querySpecNode, context) } candidates.should.have.size(2) } @@ -190,13 +190,15 @@ class QueryOperationInvocationStrategyTest { fun getQuerySpecNode(taxiQl: String, schema: TaxiSchema): Pair { val (vyne, _) = testVyne(schema) val vyneQuery = Compiler(source = taxiQl, importSources = listOf(schema.document)).queries().first() - val (context, expression) = vyne.buildContextAndExpression( - vyneQuery, - queryId = UUID.randomUUID().toString(), - clientQueryId = null, - queryOptions = QueryOptions.default(), - querySchema = vyne.schema - ) + val (context, expression) = kotlinx.coroutines.runBlocking { + vyne.buildContextAndExpression( + vyneQuery, + queryId = UUID.randomUUID().toString(), + clientQueryId = null, + queryOptions = QueryOptions.default(), + querySchema = vyne.schema + ) + } val queryParser = QueryParser(schema) val querySpecNodes = queryParser.parse(expression) return context to querySpecNodes.first() diff --git a/taxiql-query-engine/src/test/java/com/orbitalhq/query/queryBuilders/TaxiQlGrammarQueryBuilderTest.kt b/taxiql-query-engine/src/test/java/com/orbitalhq/query/queryBuilders/TaxiQlGrammarQueryBuilderTest.kt index 681a86e331..5d59ad6952 100644 --- a/taxiql-query-engine/src/test/java/com/orbitalhq/query/queryBuilders/TaxiQlGrammarQueryBuilderTest.kt +++ b/taxiql-query-engine/src/test/java/com/orbitalhq/query/queryBuilders/TaxiQlGrammarQueryBuilderTest.kt @@ -133,8 +133,9 @@ LastUpdated >= "2025-05-10T09:30:00Z" private fun generateQuery(querySpecNode: Pair): String { val (context, spec) = querySpecNode - val generated = + val generated = kotlinx.coroutines.runBlocking { queryBuilder.buildQuery(spec, schema.tableOperations.first().queryOperations.first(), schema, context) + } return generated.entries.single().value.toRawObject() as String } } diff --git a/test-utils/pom.xml b/test-utils/pom.xml index fef5ead350..acecf25369 100644 --- a/test-utils/pom.xml +++ b/test-utils/pom.xml @@ -6,7 +6,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT test-utils diff --git a/utils/pom.xml b/utils/pom.xml index 794c6779cf..ca078717f0 100644 --- a/utils/pom.xml +++ b/utils/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/utils/src/main/java/com/orbitalhq/utils/TimeBucketed.kt b/utils/src/main/java/com/orbitalhq/utils/TimeBucketed.kt index 630c956fc9..9d61ecf427 100644 --- a/utils/src/main/java/com/orbitalhq/utils/TimeBucketed.kt +++ b/utils/src/main/java/com/orbitalhq/utils/TimeBucketed.kt @@ -26,7 +26,7 @@ class TimeBucketed { } -fun timeBucket(name: String, bucket:TimeBucketed = TimeBucketed.DEFAULT, lambda: () -> T):T { +inline fun timeBucket(name: String, bucket:TimeBucketed = TimeBucketed.DEFAULT, lambda: () -> T):T { val sw = Stopwatch.createStarted() val result = lambda() bucket.addActivity(name, sw.elapsed()) diff --git a/utils/src/main/java/com/orbitalhq/utils/Timed.kt b/utils/src/main/java/com/orbitalhq/utils/Timed.kt index c6bc4359b9..a8453a1731 100644 --- a/utils/src/main/java/com/orbitalhq/utils/Timed.kt +++ b/utils/src/main/java/com/orbitalhq/utils/Timed.kt @@ -8,7 +8,7 @@ object Timer { val log = Timer.log() } -fun xtimed(name: String, log: Boolean = false, timeUnit: TimeUnit = TimeUnit.MILLISECONDS, block: () -> T): T { +inline fun xtimed(name: String, log: Boolean = false, timeUnit: TimeUnit = TimeUnit.MILLISECONDS, block: () -> T): T { return block() } diff --git a/vyne-analytics-server/pom.xml b/vyne-analytics-server/pom.xml index 61fefba31a..a7556d686c 100644 --- a/vyne-analytics-server/pom.xml +++ b/vyne-analytics-server/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/vyne-client-spring/pom.xml b/vyne-client-spring/pom.xml index 9ce25152b1..c4548f0b58 100644 --- a/vyne-client-spring/pom.xml +++ b/vyne-client-spring/pom.xml @@ -3,7 +3,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/vyne-client/pom.xml b/vyne-client/pom.xml index bfd54d7ebd..94d088168c 100644 --- a/vyne-client/pom.xml +++ b/vyne-client/pom.xml @@ -4,7 +4,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/vyne-core-types/pom.xml b/vyne-core-types/pom.xml index 93bc808a3d..a8e6a41a45 100644 --- a/vyne-core-types/pom.xml +++ b/vyne-core-types/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/vyne-core-types/src/main/java/com/orbitalhq/formats/csv/CsvCollectionParser.kt b/vyne-core-types/src/main/java/com/orbitalhq/formats/csv/CsvCollectionParser.kt index 061949a537..b09f67181e 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/formats/csv/CsvCollectionParser.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/formats/csv/CsvCollectionParser.kt @@ -26,17 +26,20 @@ class CsvCollectionParser(val content: String, } fun parse(): TypedInstance { - val typedInstances = content.lineSequence() - .drop(1) // Ignore the header - .filter { it.isNotBlank() && it.isNotEmpty() } - .map { TypedObjectFactory(memberType,it,schema, - source = source, - functionRegistry = functionRegistry, - inPlaceQueryEngine = inPlaceQueryEngine, - formatSpecs = emptyList(), - metadata = metadata - ).build() } - .toList() + val typedInstances = kotlinx.coroutines.runBlocking { + content.lineSequence() + .drop(1) // Ignore the header + .filter { it.isNotBlank() && it.isNotEmpty() } + .map { line -> TypedObjectFactory(memberType,line,schema, + source = source, + functionRegistry = functionRegistry, + inPlaceQueryEngine = inPlaceQueryEngine, + formatSpecs = emptyList(), + metadata = metadata + ) } + .toList() + .map { it.build() } + } return TypedCollection.from(typedInstances, source) } diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/AccessorReader.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/AccessorReader.kt index 32fbc804da..98cac97cb7 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/AccessorReader.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/AccessorReader.kt @@ -29,7 +29,6 @@ import com.orbitalhq.utils.timeBucket import com.orbitalhq.utils.xtimed import kotlinx.coroutines.flow.toCollection import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.runBlocking import lang.taxi.accessors.Accessor import lang.taxi.accessors.ColumnAccessor import lang.taxi.accessors.ConditionalAccessor @@ -85,7 +84,7 @@ object Parsers { interface AccessorHandler { val accessorType: KClass - fun process( + suspend fun process( accessor: T, objectFactory: EvaluationValueSupplier, schema: Schema, @@ -130,7 +129,7 @@ class AccessorReader( ) } - fun read( + suspend fun read( value: Any, targetTypeRef: QualifiedName, accessor: Accessor, @@ -145,7 +144,7 @@ class AccessorReader( return read(value, targetType, accessor, schema, nullValues, source, format, nullable, allowContextQuerying) } - fun read( + suspend fun read( value: Any, targetType: Type, accessor: Accessor, @@ -436,7 +435,7 @@ class AccessorReader( } } - private fun evaluateOperationExpression( + private suspend fun evaluateOperationExpression( value: Any, type: Type, accessor: OperationInvocationExpression, @@ -461,10 +460,8 @@ class AccessorReader( parameter to scopedFact.fact } require(operation.operationKind != OperationKind.Stream) { "Operation ${operation.name} returns a stream, which is not supported for in-place operation calls. Try querying with stream { ${operation.returnType.typeParameters[0].paramaterizedName} }"} - val result = runBlocking { - objectFactory.invokeOperation(service, operation, parameters) + val result = objectFactory.invokeOperation(service, operation, parameters) .toList() - } val accessorResult = when { operation.returnType.isCollection -> TypedCollection.arrayOf(operation.returnType, result) result.size == 1 -> result.single() @@ -474,7 +471,7 @@ class AccessorReader( return accessorResult } - private fun evaluateNegatedExpression( + private suspend fun evaluateNegatedExpression( value: Any, type: Type, accessor: NegatedExpression, @@ -514,7 +511,7 @@ class AccessorReader( } } - private fun evaluateProjectingExpression( + private suspend fun evaluateProjectingExpression( value: Any, targetType: Type, accessor: ProjectingExpression, @@ -577,7 +574,7 @@ class AccessorReader( } - private fun readModelAttributeSelector( + private suspend fun readModelAttributeSelector( accessor: MemberTypeReferenceExpression, allowContextQuerying: Boolean, schema: Schema, @@ -672,7 +669,7 @@ class AccessorReader( * - A TypeExpression: Foo (requesting a type) * - An ExpressionType: Foo = Thing + 2 (A type that has an expression) */ - private fun evaluateExpressionType( + private suspend fun evaluateExpressionType( requestedType: Type, source: Any ): TypedInstance { @@ -687,7 +684,7 @@ class AccessorReader( * - A request for an instance of that type, looked up from the objectFactory (if the return type is T) * - A request for a reference to the type itself, for reflection purposes (if the return type is Type) */ - private fun readTypeExpression( + private suspend fun readTypeExpression( accessor: TypeExpression, allowContextQuerying: Boolean, targetType: Type, @@ -719,7 +716,7 @@ class AccessorReader( return result } - private fun readScopedReferenceSelector(value: Any, accessor: ArgumentSelector): TypedInstance { + private suspend fun readScopedReferenceSelector(value: Any, accessor: ArgumentSelector): TypedInstance { val scopedInstance = if (value is FactBag) { value.getScopedFactOrNull(accessor.scope)?.fact @@ -745,7 +742,7 @@ class AccessorReader( return result } - private fun evaluateFieldReference( + private suspend fun evaluateFieldReference( targetType: Type, selectors: List, source: DataSource, @@ -815,7 +812,7 @@ class AccessorReader( } } - private fun evaluateFunctionAccessor( + private suspend fun evaluateFunctionAccessor( value: Any, targetType: Type, schema: Schema, @@ -882,7 +879,7 @@ class AccessorReader( return functionResult } - private fun collateInputsForAccessor( + private suspend fun collateInputsForAccessor( accessor: CallableInvocationExpression, schema: Schema, value: Any, @@ -973,7 +970,7 @@ class AccessorReader( return declaredInputs } - private fun invokeFunctionBody( + private suspend fun invokeFunctionBody( varArgsParam: Parameter?, varArgsValue: List, declaredInputs: List, @@ -1015,7 +1012,7 @@ class AccessorReader( } } - private fun evaluateFunctionExpressionAccessor( + private suspend fun evaluateFunctionExpressionAccessor( value: Any, targetType: Type, schema: Schema, @@ -1060,7 +1057,7 @@ class AccessorReader( } } - private fun evaluateReadFunctionAccessor( + private suspend fun evaluateReadFunctionAccessor( value: Any, targetType: Type, schema: Schema, @@ -1094,7 +1091,7 @@ class AccessorReader( return TypedInstance.from(targetType, builder.toString(), schema, source = source) } - private fun evaluateConditionalAccessor( + private suspend fun evaluateConditionalAccessor( value: Any, targetType: Type, schema: Schema, @@ -1140,7 +1137,7 @@ class AccessorReader( } } - private fun parseDestructured( + private suspend fun parseDestructured( value: Any, targetType: Type, schema: Schema, @@ -1237,7 +1234,7 @@ class AccessorReader( } - fun evaluate( + suspend fun evaluate( value: Any, returnType: Type, expression: Expression, @@ -1417,7 +1414,7 @@ class AccessorReader( } - private fun evaluateMemberAccessExpression( + private suspend fun evaluateMemberAccessExpression( value: Any, returnType: Type, expression: MemberAccessExpression, @@ -1435,7 +1432,7 @@ class AccessorReader( ) } - private fun evaluateExtensionFunctionExpression( + private suspend fun evaluateExtensionFunctionExpression( value: Any, returnType: Type, expression: ExtensionFunctionExpression, @@ -1457,7 +1454,7 @@ class AccessorReader( ) } - private fun evaluateLambdaExpression( + private suspend fun evaluateLambdaExpression( value: Any, returnType: Type, expression: LambdaExpression, @@ -1471,7 +1468,7 @@ class AccessorReader( return evaluate(value, returnType, expression.expression, schema, nullValues, dataSource, format) } - private fun evaluateFunctionExpression( + private suspend fun evaluateFunctionExpression( value: Any, returnType: Type, expression: FunctionExpression, @@ -1494,11 +1491,11 @@ class AccessorReader( ) } - private fun evaluateTypeExpression(expression: TypeExpression, schema: Schema): TypedInstance { + private suspend fun evaluateTypeExpression(expression: TypeExpression, schema: Schema): TypedInstance { return objectFactory.getValue(expression.type.toVyneQualifiedName(), queryIfNotFound = true) } - private fun evaluateOperatorExpression( + private suspend fun evaluateOperatorExpression( returnType: Type, expression: OperatorExpression, schema: Schema, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/DeferredExpression.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/DeferredExpression.kt index dc3ca5c2db..882a3336ee 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/DeferredExpression.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/DeferredExpression.kt @@ -35,7 +35,7 @@ class DeferredExpression( return equality.isEqualTo(other) } - override fun evaluate( + override suspend fun evaluate( input: TypedInstance, dataSource: DataSource, evaluationValueSupplier: EvaluationValueSupplier, @@ -94,7 +94,7 @@ data class DeferredProjection( return equality.isEqualTo(other) } - override fun evaluate( + override suspend fun evaluate( input: TypedInstance, dataSource: DataSource, evaluationValueSupplier: EvaluationValueSupplier, @@ -132,7 +132,7 @@ interface DeferredTypedInstance : TypedInstance { TODO("Not yet implemented") } - fun evaluate( + suspend fun evaluate( input: TypedInstance, dataSource: DataSource, evaluationValueSupplier: EvaluationValueSupplier, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/EvaluationValueSupplier.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/EvaluationValueSupplier.kt index 2b3b18895b..5c71971efc 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/EvaluationValueSupplier.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/EvaluationValueSupplier.kt @@ -21,15 +21,15 @@ import lang.taxi.types.FormatsAndZoneOffset * Generally a TypedObjectFactory */ interface EvaluationValueSupplier : ScopedValueProvider { - fun getValue( + suspend fun getValue( typeName: QualifiedName, queryIfNotFound: Boolean = false, allowAccessorEvaluation: Boolean = true, constraints: List = emptyList() ): TypedInstance - fun readAccessor(type: Type, accessor: Accessor, format: FormatsAndZoneOffset?): TypedInstance - fun readAccessor(type: QualifiedName, accessor: Accessor, nullable: Boolean, format: FormatsAndZoneOffset?): TypedInstance + suspend fun readAccessor(type: Type, accessor: Accessor, format: FormatsAndZoneOffset?): TypedInstance + suspend fun readAccessor(type: QualifiedName, accessor: Accessor, nullable: Boolean, format: FormatsAndZoneOffset?): TypedInstance /** * If the EvaluationValueSupplier has access to a queryEngine, it should @@ -50,9 +50,9 @@ interface EvaluationValueSupplier : ScopedValueProvider { interface ScopedValueProvider { fun getScopedFact(scope: Argument): TypedInstance fun getScopedFactOrNull(scope: Argument): TypedInstance? - fun getValue(attributeName: AttributeName): TypedInstance + suspend fun getValue(attributeName: AttributeName): TypedInstance - fun withAdditionalScopedFacts(scopedFacts: List):ScopedValueProvider + suspend fun withAdditionalScopedFacts(scopedFacts: List):ScopedValueProvider } class FactBagScopeValueProvider(private val factBag: FactBag, private val schema: Schema):ScopedValueProvider { @@ -65,11 +65,11 @@ class FactBagScopeValueProvider(private val factBag: FactBag, private val schema } - override fun getValue(attributeName: AttributeName): TypedInstance { + override suspend fun getValue(attributeName: AttributeName): TypedInstance { TODO("Not yet implemented") } - override fun withAdditionalScopedFacts(scopedFacts: List): ScopedValueProvider { + override suspend fun withAdditionalScopedFacts(scopedFacts: List): ScopedValueProvider { return FactBagScopeValueProvider( factBag.withAdditionalScopedFacts(scopedFacts, schema), schema diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/FactBagValueSupplier.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/FactBagValueSupplier.kt index f79dee44ef..7a2504df27 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/FactBagValueSupplier.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/FactBagValueSupplier.kt @@ -49,7 +49,7 @@ class FactBagValueSupplier( override val hasDataContext: Boolean = true override val dataContext: SearchableDataContext = facts - override fun withAdditionalScopedFacts(scopedFacts: List): FactBagValueSupplier { + override suspend fun withAdditionalScopedFacts(scopedFacts: List): FactBagValueSupplier { return FactBagValueSupplier( this.facts, @@ -67,7 +67,7 @@ class FactBagValueSupplier( } } - override fun getValue( + override suspend fun getValue( typeName: QualifiedName, queryIfNotFound: Boolean, allowAccessorEvaluation: Boolean, @@ -88,7 +88,7 @@ class FactBagValueSupplier( ) } - override fun getValue(attributeName: AttributeName): TypedInstance { + override suspend fun getValue(attributeName: AttributeName): TypedInstance { return scopedValueProvider.getValue(attributeName) } @@ -100,12 +100,12 @@ class FactBagValueSupplier( return scopedValueProvider.getScopedFactOrNull(scope) } - override fun readAccessor(type: Type, accessor: Accessor, format: FormatsAndZoneOffset?): TypedInstance { + override suspend fun readAccessor(type: Type, accessor: Accessor, format: FormatsAndZoneOffset?): TypedInstance { // This method shouldn't be called. error("readAccessor is not supported by this class") } - override fun readAccessor( + override suspend fun readAccessor( type: QualifiedName, accessor: Accessor, nullable: Boolean, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/InPlaceQueryEngine.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/InPlaceQueryEngine.kt index 2f05901bdb..ae0ccf07a4 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/InPlaceQueryEngine.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/InPlaceQueryEngine.kt @@ -54,8 +54,8 @@ interface InPlaceQueryEngine : FactBag, QueryContextSchemaProvider { fun withAdditionalFacts(facts: List, scopedFacts: List): InPlaceQueryEngine - fun evaluate(expression: Expression, facts: FactBag = FactBag.empty(), source:DataSource = Provided): TypedInstance - fun evaluate(expression: Expression, value:TypedInstance, source:DataSource = Provided): TypedInstance + suspend fun evaluate(expression: Expression, facts: FactBag = FactBag.empty(), source:DataSource = Provided): TypedInstance + suspend fun evaluate(expression: Expression, value:TypedInstance, source:DataSource = Provided): TypedInstance // See ProjectionFunctionScopeEvaluator.queryContextForFact // this method will need to be implemented eventually diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/ProjectionFunctionScopeEvaluator.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/ProjectionFunctionScopeEvaluator.kt index 02be9cba1b..28c0d2e4d9 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/ProjectionFunctionScopeEvaluator.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/ProjectionFunctionScopeEvaluator.kt @@ -5,7 +5,6 @@ import com.orbitalhq.models.facts.FactDiscoveryStrategy import com.orbitalhq.models.facts.ScopedFact import com.orbitalhq.schemas.Type import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.runBlocking import lang.taxi.accessors.Argument import lang.taxi.accessors.ProjectionFunctionScope import lang.taxi.types.ArrayType @@ -34,7 +33,7 @@ import lang.taxi.types.StreamType * */ object ProjectionFunctionScopeEvaluator { - fun build( + suspend fun build( inputs: List, primaryFacts: List, context: InPlaceQueryEngine, @@ -57,9 +56,7 @@ object ProjectionFunctionScopeEvaluator { val fact = FactBag.of(primaryFacts, schema) .getFactOrNull(scopeType, FactDiscoveryStrategy.ANY_DEPTH_EXPECT_ONE_DISTINCT) // If that didn't work, do a proper search - fact ?: runBlocking { - queryContextForFact(context, primaryFacts, scopeType) - } + fact ?: queryContextForFact(context, primaryFacts, scopeType) } } catch (e: Exception) { diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/TypedObject.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/TypedObject.kt index 2fac03c7cc..69b9053fe6 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/TypedObject.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/TypedObject.kt @@ -97,22 +97,24 @@ data class TypedObject( valueSuppliers: List = emptyList(), parsingOptions: ParsingOptions = ParsingOptions.DEFAULT ): TypedInstance { - return TypedObjectFactory( - type, - value, - schema, - nullValues, - source, - evaluateAccessors = evaluateAccessors, - functionRegistry = functionRegistry, - inPlaceQueryEngine = inPlaceQueryEngine, - formatSpecs = formatSpecs, - parsingErrorBehaviour = parsingErrorBehaviour, - functionResultCache = functionResultCache, - metadata = metadata, - valueSuppliers = valueSuppliers, - parsingOptions = parsingOptions - ).build() + return kotlinx.coroutines.runBlocking { + TypedObjectFactory( + type, + value, + schema, + nullValues, + source, + evaluateAccessors = evaluateAccessors, + functionRegistry = functionRegistry, + inPlaceQueryEngine = inPlaceQueryEngine, + formatSpecs = formatSpecs, + parsingErrorBehaviour = parsingErrorBehaviour, + functionResultCache = functionResultCache, + metadata = metadata, + valueSuppliers = valueSuppliers, + parsingOptions = parsingOptions + ).build() + } } } diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/TypedObjectFactory.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/TypedObjectFactory.kt index fb05a58176..b1bdd41480 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/TypedObjectFactory.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/TypedObjectFactory.kt @@ -19,9 +19,12 @@ import com.orbitalhq.schemas.* import com.orbitalhq.schemas.taxi.toVyneQualifiedName import com.orbitalhq.utils.timeBucket import com.orbitalhq.utils.xtimed +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.runBlocking import lang.taxi.accessors.* import lang.taxi.expressions.Expression import lang.taxi.expressions.LambdaExpression @@ -32,7 +35,6 @@ import lang.taxi.types.FormatsAndZoneOffset import mu.KotlinLogging import org.apache.commons.csv.CSVRecord import java.util.concurrent.CopyOnWriteArrayList -import java.util.stream.Collectors /** @@ -85,10 +87,15 @@ class TypedObjectFactory( ) : EvaluationValueSupplier, ValueProjector, OperationInvokerContainer { - companion object { + private companion object { private val logger = KotlinLogging.logger {} + + val parallelism = Runtime.getRuntime().availableProcessors() + val limitedParallelismDispatcher = Dispatchers.Default.limitedParallelism(parallelism) + } + private val buildSpecProvider = TypedInstancePredicateFactory() private val valueReader = ValueReader() @@ -147,52 +154,13 @@ class TypedObjectFactory( private val attributesToMap = type.attributes - private val fieldInitializers: Map> by lazy { - attributesToMap.map { (attributeName, field) -> - attributeName to lazy { - - val fieldValue = - xtimed("build field $attributeName ${field.typeDisplayName}") { - buildField( - field, - attributeName - ) - }.let { constructedField -> - if (policyEngine != null && inPlaceQueryEngine != null) { - policyEngine.evaluate(constructedField, inPlaceQueryEngine) - } else { - constructedField - } - } - - // Do not start a projection if the type we're projecting to is the same as the value we have. - // This happens if the projection was processed internally already within the object construction - if (field.fieldProjection != null && !field.fieldProjection.projectedType.isAssignableTo(fieldValue.type.taxiType, - // Structural compatability is useful when assigning a value, but not - // when determining if we want to project. - // At projection time, the goal is to create an object that looks exactly like the provided spec. - // If the source value (ie., fieldValue) is a superset of the projectedType, that would pass structural - // compatability, but isn't what we want. - // eg: - // model EnhancedPerson { Name, Age } - // model Person { Name } - // If we project EnhancedPerson to Person, we want the Age field dropped, even though - // the two types match from a structuralCompatability perspective. - permitStructurallyCompatible = false)) { - val projection = xtimed("Project field $attributeName") { - projectField( - field, - fieldValue, - ) - } - projection - } else { - fieldValue - } - } - }.toMap() - } + /** + * Cache for computed field values. Replaces the previous lazy delegate map. + * Since a single factory instance is only accessed from one coroutine at a time, + * a plain HashMap is sufficient — no synchronization needed. + */ + private val fieldValues: MutableMap = HashMap() /** * Where a field has an inline projection defined ( @@ -200,7 +168,7 @@ class TypedObjectFactory( * a : A, b: B * } */ - private fun projectField( + private suspend fun projectField( field: Field, fieldValue: TypedInstance, ): TypedInstance { @@ -231,7 +199,7 @@ class TypedObjectFactory( ) } - override fun project( + override suspend fun project( valueToProject: TypedInstance, projection: FieldProjection, targetType: Type, @@ -255,21 +223,23 @@ class TypedObjectFactory( ) } val projectedFieldValue = if (valueToProject is TypedCollection && targetType.isCollection) { - // Project each member of the collection seperately - valueToProject - .parallelStream() - .map { collectionMember -> - newFactory( - targetType.collectionType!!, - collectionMember, - scopedArguments = projection.projectionFunctionScope - ) - .build() - }.collect(Collectors.toList()) - .let { projectedCollection -> - // Use arrayOf (instead of from), as the collection may be empty, so we want to be explicit about it's type - TypedCollection.arrayOf(targetType.collectionType!!, projectedCollection, source) - } + // Project each member of the collection using coroutines instead of parallelStream + + coroutineScope { + valueToProject.map { collectionMember -> + async(limitedParallelismDispatcher) { + newFactory( + targetType.collectionType!!, + collectionMember, + scopedArguments = projection.projectionFunctionScope + ) + .build() + } + }.awaitAll() + }.let { projectedCollection -> + // Use arrayOf (instead of from), as the collection may be empty, so we want to be explicit about it's type + TypedCollection.arrayOf(targetType.collectionType!!, projectedCollection, source) + } } else { newFactory(targetType, valueToProject, scopedArguments = projection.projectionFunctionScope).build() } @@ -315,7 +285,7 @@ class TypedObjectFactory( * Returns a new TypedObjectFactory, * merging the current set of known values with the newValue if possible. */ - fun newFactory( + suspend fun newFactory( type: Type, newValue: Any, factsToExclude: Set = emptySet(), @@ -419,7 +389,7 @@ class TypedObjectFactory( return TypedObject(type, attributes, source, metadata) } - fun build(decorator: (attributeMap: Map) -> Map = { attributesToMap -> attributesToMap }): TypedInstance { + suspend fun build(decorator: suspend (attributeMap: Map) -> Map = { attributesToMap -> attributesToMap }): TypedInstance { return timeBucket("Build ${this.type.name.shortDisplayName}") { doBuild(decorator) } @@ -460,7 +430,7 @@ class TypedObjectFactory( ) } - private fun doBuild(decorator: (attributeMap: Map) -> Map = { attributesToMap -> attributesToMap }): TypedInstance { + private suspend fun doBuild(decorator: suspend (attributeMap: Map) -> Map = { attributesToMap -> attributesToMap }): TypedInstance { val metadataAndFormat = formatDetector.getFormatType(type) if (metadataAndFormat != null) { val (metadata, modelFormatSpec) = metadataAndFormat @@ -548,7 +518,7 @@ class TypedObjectFactory( /** * Called because the parent type is closed, so construction isn't possible */ - private fun queryForParentType(): TypedInstance { + private suspend fun queryForParentType(): TypedInstance { if (inPlaceQueryEngine == null) { return TypedNull.create( type, @@ -556,29 +526,50 @@ class TypedObjectFactory( ) } val searchFailureBehaviour: QueryFailureBehaviour = QueryFailureBehaviour.defaultBehaviour(type) - return runBlocking { - logger.debug { "Initiating query to search for closed type ${type.name.shortDisplayName}" } - queryForType(type, searchFailureBehaviour, AlwaysGoodSpec, attributeName = null) - } - - + logger.debug { "Initiating query to search for closed type ${type.name.shortDisplayName}" } + return queryForType(type, searchFailureBehaviour, AlwaysGoodSpec, attributeName = null) } - private fun getOrBuild(attributeName: AttributeName, allowAccessorEvaluation: Boolean = true): TypedInstance { - // Originally we used a concurrentHashMap.computeIfAbsent { ... } approach here. - // However, functions on accessors can access other fields, which can cause recursive access. - // Therefore, migrated to using initializers with kotlin Lazy functions - val initializer = fieldInitializers[attributeName] - ?: error("Cannot request field $attributeName as no initializer has been prepared") + private suspend fun getOrBuild(attributeName: AttributeName, allowAccessorEvaluation: Boolean = true): TypedInstance { + // Check cache first — if the field was already computed (e.g. via cross-field reference), return it + fieldValues[attributeName]?.let { return it } + + val field = attributesToMap[attributeName] + ?: error("Cannot request field $attributeName as no attribute definition exists") val accessorEvaluationWasSupressed = accessorEvaluationSupressed accessorEvaluationSupressed = !allowAccessorEvaluation - // Reading the value will trigger population the first time. - val value = initializer.value + val fieldValue = + xtimed("build field $attributeName ${field.typeDisplayName}") { + buildField(field, attributeName) + }.let { constructedField -> + if (policyEngine != null && inPlaceQueryEngine != null) { + policyEngine.evaluate(constructedField, inPlaceQueryEngine) + } else { + constructedField + } + } + + // Do not start a projection if the type we're projecting to is the same as the value we have. + // This happens if the projection was processed internally already within the object construction + val result = if (field.fieldProjection != null && !field.fieldProjection.projectedType.isAssignableTo( + fieldValue.type.taxiType, + permitStructurallyCompatible = false + ) + ) { + xtimed("Project field $attributeName") { + projectField(field, fieldValue) + } + } else { + fieldValue + } accessorEvaluationSupressed = accessorEvaluationWasSupressed - return value + + // Cache the result for cross-field references + fieldValues[attributeName] = result + return result } override fun getScopedFact(scope: Argument): TypedInstance { @@ -597,7 +588,7 @@ class TypedObjectFactory( } } - override fun withAdditionalScopedFacts(scopedFacts: List): TypedObjectFactory { + override suspend fun withAdditionalScopedFacts(scopedFacts: List): TypedObjectFactory { return when (value) { is FactBag -> newFactory( this.type, value.withAdditionalScopedFacts(scopedFacts, this.schema), @@ -620,7 +611,7 @@ class TypedObjectFactory( /** * Returns a value looked up by it's type */ - override fun getValue( + override suspend fun getValue( typeName: QualifiedName, queryIfNotFound: Boolean, allowAccessorEvaluation: Boolean, @@ -665,7 +656,7 @@ class TypedObjectFactory( } } - private fun handleTypeNotFound( + private suspend fun handleTypeNotFound( requestedType: Type, queryIfNotFound: Boolean, constraints: List @@ -683,75 +674,47 @@ class TypedObjectFactory( } return when { queryIfNotFound && inPlaceQueryEngine != null -> { - // TODO : Remove the blocking behaviour here. - // TypedObjectFactory has always been blocking (but - // historically hasn't invoked services), so leaving as - // blocking when introducing type expressions with lookups. - // However, in future, we need to mkae the TypedObjectFactory - // async up the chain. - runBlocking { - if (requestedType.isStream) { - error("Cannot perform an inner search for a stream") + if (requestedType.isStream) { + error("Cannot perform an inner search for a stream") + } + val resultsFromSearch = try { + val queryEngine = if (value is FactBag) { + inPlaceQueryEngine.withAdditionalFacts(value.rootFacts(), value.scopedFacts) + } else { + inPlaceQueryEngine } - val resultsFromSearch = try { - // MP: 29-Jan-25: Found that facts from the context - // are not being passed when doing an in-place search - // So, in a nested projection, we were not searching with the facts - // from the current scope. - val queryEngine = if (value is FactBag) { - inPlaceQueryEngine.withAdditionalFacts(value.rootFacts(), value.scopedFacts) - } else { - inPlaceQueryEngine - } - queryEngine.findType(requestedType, constraints = constraints) - .toList() - } catch (e: Exception) { - // OrbitalQueryException comes from a policy expression: e.g.when below `else` branch is triggered: - /*policy AdminRestrictedInstrument against Instrument (userInfo : UserInfo) -> { - read { - when { - userInfo.roles.contains('QueryRunner') -> Instrument - else -> throw((NotAuthorizedError) { message: 'Not Authorized' }) - } - } - }*/ - // so, we need to catch OrbitalQueryException and re-throw to halt the execution. - // a query like find { fist(Instrument[]) } against the above policy would hit the debug point placed here. - if (e is OrbitalQueryException) { - throw e - } - - // handle com.orbitalhq.query.UnresolvedTypeInQueryException - emptyList() + queryEngine.findType(requestedType, constraints = constraints) + .toList() + } catch (e: Exception) { + if (e is OrbitalQueryException) { + throw e } - when { - resultsFromSearch.isEmpty() -> createTypedNull( - "No attribute with type ${requestedType.name.parameterizedName} is present on type ${type.name.parameterizedName} and attempts to discover a value from the query engine did not find any approaches that produced a result" - ) - - resultsFromSearch.size == 1 && !requestedType.isCollection -> resultsFromSearch.first() + emptyList() + } + when { + resultsFromSearch.isEmpty() -> createTypedNull( + "No attribute with type ${requestedType.name.parameterizedName} is present on type ${type.name.parameterizedName} and attempts to discover a value from the query engine did not find any approaches that produced a result" + ) - // MP: 15-Jul-25: A search for T[] that produced null, hits here with a single TypedNull -- don't wrap that into a collection - resultsFromSearch.size == 1 && requestedType.isCollection && resultsFromSearch.single() is TypedNull && resultsFromSearch.single().type.isCollection -> resultsFromSearch.single() - resultsFromSearch.size >= 1 && requestedType.isCollection -> TypedCollection.from( - resultsFromSearch, - MixedSources.singleSourceOrMixedSources(resultsFromSearch) - ) + resultsFromSearch.size == 1 && !requestedType.isCollection -> resultsFromSearch.first() - resultsFromSearch.size > 1 && !requestedType.isCollection -> { - val errorMessage = - "Search for ${requestedType.name.shortDisplayName} returned ${resultsFromSearch.size} results, which is invalid for non-array types. Returning null." - logger.warn { errorMessage } - createTypedNull(errorMessage) - } + resultsFromSearch.size == 1 && requestedType.isCollection && resultsFromSearch.single() is TypedNull && resultsFromSearch.single().type.isCollection -> resultsFromSearch.single() + resultsFromSearch.size >= 1 && requestedType.isCollection -> TypedCollection.from( + resultsFromSearch, + MixedSources.singleSourceOrMixedSources(resultsFromSearch) + ) - else -> createTypedNull( - "No attribute with type ${requestedType.name.parameterizedName} is present on type ${type.name.parameterizedName} and attempts to discover a value from the query engine returned ${resultsFromSearch.size} results. Given this is ambiguous, returning null" - ) + resultsFromSearch.size > 1 && !requestedType.isCollection -> { + val errorMessage = + "Search for ${requestedType.name.shortDisplayName} returned ${resultsFromSearch.size} results, which is invalid for non-array types. Returning null." + logger.warn { errorMessage } + createTypedNull(errorMessage) } + else -> createTypedNull( + "No attribute with type ${requestedType.name.parameterizedName} is present on type ${type.name.parameterizedName} and attempts to discover a value from the query engine returned ${resultsFromSearch.size} results. Given this is ambiguous, returning null" + ) } - } queryIfNotFound && inPlaceQueryEngine == null -> { @@ -766,18 +729,18 @@ class TypedObjectFactory( } - private fun getValue(attributeName: AttributeName, allowAccessorEvaluation: Boolean): TypedInstance { + private suspend fun getValue(attributeName: AttributeName, allowAccessorEvaluation: Boolean): TypedInstance { return getOrBuild(attributeName, allowAccessorEvaluation) } /** * Returns a value looked up by it's name */ - override fun getValue(attributeName: AttributeName): TypedInstance { + override suspend fun getValue(attributeName: AttributeName): TypedInstance { return getValue(attributeName, allowAccessorEvaluation = true) } - override fun readAccessor(type: Type, accessor: Accessor, format: FormatsAndZoneOffset?): TypedInstance { + override suspend fun readAccessor(type: Type, accessor: Accessor, format: FormatsAndZoneOffset?): TypedInstance { // MP 24-Jan-25: // Changed this to allowContextQuerying = true. // Otherwise, types on projections-with-expressions were not triggering querying - eg: @@ -799,7 +762,7 @@ class TypedObjectFactory( ) } - override fun readAccessor( + override suspend fun readAccessor( type: QualifiedName, accessor: Accessor, nullable: Boolean, @@ -818,7 +781,7 @@ class TypedObjectFactory( ) } - fun evaluateExpressionType(expressionType: Type, format: FormatsAndZoneOffset?): TypedInstance { + suspend fun evaluateExpressionType(expressionType: Type, format: FormatsAndZoneOffset?): TypedInstance { val expression = expressionType.expression!! return if (expression is LambdaExpression) { // Lambda Expression types are evaluated more like functions. @@ -836,7 +799,7 @@ class TypedObjectFactory( } - fun evaluateLambdaExpression(expression: LambdaExpression, format: FormatsAndZoneOffset?): TypedInstance { + suspend fun evaluateLambdaExpression(expression: LambdaExpression, format: FormatsAndZoneOffset?): TypedInstance { // Lambda Expression types are evaluated more like functions. // Their inputs are declared independent of queries where they're evaluated // eg: @@ -882,29 +845,24 @@ class TypedObjectFactory( // The inputs into this expression have constraints defined. // We can't search directly for the type, we need to do a search for the type with the provided constraints. val argumentTypeExpression = argument.expression as TypeExpression - // TODO : Fix runblocking, but that requires a big change, and not sure the direction of travel - // wrt/ coroutines vs flux atm. val argumentExpressionReturnType = schema.type(argumentTypeExpression.type) val scopedFacts = this.getCurrentScopedFacts() - val typedInstance = runBlocking { - // If we're doing nested traversal of lambda expressions, - // there could be scoped facts we've been passed that will - // be needed as inputs - - val queryEngineWithScopedFacts = - valueSupplier.inPlaceQueryEngine!!.withAdditionalFacts(emptyList(), scopedFacts) - val collectedList = queryEngineWithScopedFacts.findType( - argumentExpressionReturnType, constraints = argumentTypeExpression.constraints - ).toList() - when { - argumentExpressionReturnType.isCollection -> TypedCollection.from(collectedList) - collectedList.isEmpty() -> TypedNull.create(argumentExpressionReturnType) - collectedList.size == 1 -> collectedList.single() - else -> { - error("Expected a single value returned for the expression type ${argumentTypeExpression}, but got ${collectedList.size}") - } - } + // If we're doing nested traversal of lambda expressions, + // there could be scoped facts we've been passed that will + // be needed as inputs + val queryEngineWithScopedFacts = + valueSupplier.inPlaceQueryEngine!!.withAdditionalFacts(emptyList(), scopedFacts) + val collectedList = queryEngineWithScopedFacts.findType( + argumentExpressionReturnType, constraints = argumentTypeExpression.constraints + ).toList() + val typedInstance = when { + argumentExpressionReturnType.isCollection -> TypedCollection.from(collectedList) + collectedList.isEmpty() -> TypedNull.create(argumentExpressionReturnType) + collectedList.size == 1 -> collectedList.single() + else -> { + error("Expected a single value returned for the expression type ${argumentTypeExpression}, but got ${collectedList.size}") + } } // val typedInstance = TypedInstance.from(argumentExpressionReturnType, result, schema) ScopedFact(argument, typedInstance) @@ -942,7 +900,7 @@ class TypedObjectFactory( return result } - fun evaluateExpression(expression: Expression): TypedInstance { + suspend fun evaluateExpression(expression: Expression): TypedInstance { return accessorReader.evaluate( value, schema.type(expression.returnType), @@ -954,13 +912,13 @@ class TypedObjectFactory( ) } - private fun evaluateExpressionType(typeName: QualifiedName): TypedInstance { + private suspend fun evaluateExpressionType(typeName: QualifiedName): TypedInstance { val type = schema.type(typeName) return evaluateExpressionType(type, null) } - private fun buildField(field: Field, attributeName: AttributeName): TypedInstance { + private suspend fun buildField(field: Field, attributeName: AttributeName): TypedInstance { // When we're building a field, if there's a projection on it, // we build the source type initially. Once the source is built, we // then project to the target type. @@ -1168,7 +1126,7 @@ class TypedObjectFactory( * We need to ensure that the value we're using * satisfies that constraint. Otherwise, search for it. */ - private fun verifyValueSatisfiesConstraints( + private suspend fun verifyValueSatisfiesConstraints( value: TypedInstance, field: Field, type: Type, @@ -1234,7 +1192,7 @@ class TypedObjectFactory( * That creates challenges, as we need to pass the ObjectBuilder in the TypedObjectFactory, * which becomes recursive. */ - private fun attemptToBuildFieldObject( + private suspend fun attemptToBuildFieldObject( fieldType: Type, constraints: List ): TypedInstance? { @@ -1269,7 +1227,7 @@ class TypedObjectFactory( ) } - private fun queryForFieldValue( + private suspend fun queryForFieldValue( field: Field, type: Type, attributeName: AttributeName, @@ -1290,7 +1248,7 @@ class TypedObjectFactory( } } - private fun queryForType( + private suspend fun queryForType( searchType: Type, searchFailureBehaviour: QueryFailureBehaviour, instanceValidPredicate: TypedInstanceValidPredicate, @@ -1311,18 +1269,17 @@ class TypedObjectFactory( } val (additionalFacts, additionalScope) = getFactsInScopeForSearch() - val buildResult = runBlocking { - logger.debug { "Initiating query to search for attribute $attributeName (${searchType.name.shortDisplayName})" } - inPlaceQueryEngine.withAdditionalFacts(additionalFacts, additionalScope) - .findType( - searchType, - instanceValidPredicate, - PermittedQueryStrategies.EXCLUDE_BUILDER_AND_MODEL_SCAN, - searchFailureBehaviour, - constraint - ) - .toList() - } + + logger.debug { "Initiating query to search for attribute $attributeName (${searchType.name.shortDisplayName})" } + val buildResult = inPlaceQueryEngine.withAdditionalFacts(additionalFacts, additionalScope) + .findType( + searchType, + instanceValidPredicate, + PermittedQueryStrategies.EXCLUDE_BUILDER_AND_MODEL_SCAN, + searchFailureBehaviour, + constraint + ) + .toList() val attributeNameErrorMessagePart = if (attributeName != null) { " (attempting to build attribute $attributeName of ${this.type.name}" } else "" @@ -1437,7 +1394,7 @@ class TypedObjectFactory( } - private fun readWithValueReader( + private suspend fun readWithValueReader( attributeName: AttributeName, type: Type, format: FormatsAndZoneOffset? diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/ValueProjector.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/ValueProjector.kt index bdd307da12..a4e4dbdf46 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/ValueProjector.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/ValueProjector.kt @@ -16,7 +16,7 @@ import lang.taxi.types.FormatsAndZoneOffset * which include queries etc. */ interface ValueProjector { - fun project( + suspend fun project( valueToProject: TypedInstance, projection: FieldProjection, // because the projection.targetType is a Taxi Type diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/ConditionalFieldSetEvaluator.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/ConditionalFieldSetEvaluator.kt index 282ef8b0dd..a9546fde80 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/ConditionalFieldSetEvaluator.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/ConditionalFieldSetEvaluator.kt @@ -16,7 +16,7 @@ class ConditionalFieldSetEvaluator(private val factory: EvaluationValueSupplier, // fun evaluate(readCondition: FieldSetExpression, targetType: Type): TypedInstance { // return evaluate(readCondition, attributeName = null, targetType = targetType) // } - fun evaluate(value:Any,readCondition: FieldSetExpression, attributeName: AttributeName?, targetType: Type, datasource:DataSource): TypedInstance { + suspend fun evaluate(value:Any,readCondition: FieldSetExpression, attributeName: AttributeName?, targetType: Type, datasource:DataSource): TypedInstance { TODO("Refactor when blocks") // return try { // when (readCondition) { diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/LogicalExpressionEvaluator.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/LogicalExpressionEvaluator.kt deleted file mode 100644 index 241f176fd1..0000000000 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/LogicalExpressionEvaluator.kt +++ /dev/null @@ -1,123 +0,0 @@ -package com.orbitalhq.models.conditional - -import arrow.core.Either -import arrow.core.left -import arrow.core.right -import com.orbitalhq.models.EvaluationValueSupplier -import com.orbitalhq.schemas.Type -import lang.taxi.types.AndExpression -import lang.taxi.types.ComparisonExpression -import lang.taxi.types.ComparisonOperator -import lang.taxi.types.ConstantEntity -import lang.taxi.types.ElseMatchExpression -import lang.taxi.types.FieldReferenceEntity -import lang.taxi.types.LogicalExpression -import lang.taxi.types.OrExpression -import lang.taxi.types.WhenCaseBlock -import java.math.BigDecimal -import java.util.* - -object LogicalExpressionEvaluator { - fun evaluate(cases: List, factory: EvaluationValueSupplier, type: Type): WhenCaseBlock? { - return cases.firstOrNull { case -> - when (case.matchExpression) { - is LogicalExpression -> { - val expressionStack = Stack>() - pushExpression(case.matchExpression as LogicalExpression, expressionStack) - evaluateExpressionStack(expressionStack, type, factory) - } - is ElseMatchExpression -> true - else -> false - } - } - } - - private fun pushExpression(logicalExpression: LogicalExpression, expressionStack: Stack>) { - when (logicalExpression) { - is ComparisonExpression -> expressionStack.push(logicalExpression.left()) - is AndExpression -> { - pushExpression(logicalExpression.right, expressionStack) - expressionStack.push(LogicalOp.And.right()) - pushExpression(logicalExpression.left, expressionStack) - } - is OrExpression -> { - pushExpression(logicalExpression.right, expressionStack) - expressionStack.push(LogicalOp.Or.right()) - pushExpression(logicalExpression.left, expressionStack) - } - } - } - - private fun evaluateExpressionStack(expressionStack: Stack>, type: Type, factory: EvaluationValueSupplier): Boolean { - var result = false - var lastLogicalOp: LogicalOp? = null - while (!expressionStack.empty()) { - when (val item = expressionStack.pop()) { - is Either.Left -> result = when (lastLogicalOp) { - LogicalOp.And -> result && evaluateComparisonExpression(item.value as ComparisonExpression, factory) - LogicalOp.Or -> result || evaluateComparisonExpression(item.value as ComparisonExpression, factory) - else -> evaluateComparisonExpression(item.value as ComparisonExpression, factory) - } - - is Either.Right -> lastLogicalOp = item.value - } - } - return result - } - - - private fun evaluateComparisonExpression(logicalExpression: ComparisonExpression, factory: EvaluationValueSupplier): Boolean { - val right = logicalExpression.right - val left = logicalExpression.left - val (leftValue, rightValue) = when { - right is FieldReferenceEntity && left is FieldReferenceEntity -> { - (factory.getValue(left.fieldName).value to factory.getValue(right.fieldName).value) - } - right is ConstantEntity && left is FieldReferenceEntity -> { - factory.getValue(left.fieldName).value to right.value - } - - right is FieldReferenceEntity && left is ConstantEntity -> { - left.value to factory.getValue(right.fieldName).value - } - else -> null to null - } - - return evaluateExpression(leftValue, rightValue, logicalExpression.operator) - } - - private fun evaluateExpression(left: Any?, right: Any?, operator: ComparisonOperator): Boolean { - return when { - left == null && right == null && operator == ComparisonOperator.EQ -> true - left == null && right != null && operator == ComparisonOperator.NQ -> true - left != null && right == null && operator == ComparisonOperator.NQ -> true - left != null && right != null -> evaluateExpressionForPopulatedOperands(left, right, operator) - else -> false - } - } - - private fun evaluateExpressionForPopulatedOperands(left: Any, right: Any, operator: ComparisonOperator): Boolean { - return when { - left is Int && right is Int -> evaluateComparables(left, right, operator) - left is BigDecimal && right is BigDecimal -> evaluateComparables(left, right, operator) - left is String && right is String -> evaluateComparables(left, right, operator) - else -> false - } - } - - private fun > evaluateComparables(left: T, right: T, operator: ComparisonOperator): Boolean { - return when (operator) { - ComparisonOperator.LT -> left < right - ComparisonOperator.NQ -> left != right - ComparisonOperator.EQ -> left == right - ComparisonOperator.GE -> left >= right - ComparisonOperator.GT -> left > right - ComparisonOperator.LE -> left <= right - } - } -} - -enum class LogicalOp { - And, - Or -} diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/WhenBlockEvaluator.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/WhenBlockEvaluator.kt index 66e30260ef..c7f76f4fa5 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/WhenBlockEvaluator.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/conditional/WhenBlockEvaluator.kt @@ -19,7 +19,7 @@ class WhenBlockEvaluator( private val schema: Schema, private val accessorReader: AccessorReader ) { - fun evaluate( + suspend fun evaluate( value: Any, readCondition: WhenExpression, source: DataSource, @@ -51,7 +51,7 @@ class WhenBlockEvaluator( return result } - private fun selectCaseBlock( + private suspend fun selectCaseBlock( selectorValue: TypedInstance, readCondition: WhenExpression, value: Any, @@ -88,7 +88,7 @@ class WhenBlockEvaluator( return selectedCase to EvaluatedWhenCaseSelection(readCondition.asTaxi(), selectorValue, selectedCase?.asTaxi(), evaluations) } - private fun evaluateExpression( + private suspend fun evaluateExpression( matchExpression: Expression, type: Type, value: Any, @@ -98,7 +98,7 @@ class WhenBlockEvaluator( return accessorReader.evaluate(value, type, matchExpression, dataSource = UndefinedSource, format = format) } - private fun evaluateSelector( + private suspend fun evaluateSelector( selectorExpression: WhenSelectorExpression, format: FormatsAndZoneOffset? ): TypedInstance { diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/constraints/ConstraintEvaluation.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/constraints/ConstraintEvaluation.kt index 83a8e3e087..9b84378ae1 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/constraints/ConstraintEvaluation.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/constraints/ConstraintEvaluation.kt @@ -25,7 +25,7 @@ import lang.taxi.types.ArgumentSelector import mu.KotlinLogging import kotlin.reflect.KClass -fun Constraint.evaluate( +suspend fun Constraint.evaluate( value: TypedInstance, schema: Schema, context: InPlaceQueryEngine @@ -36,7 +36,7 @@ fun Constraint.evaluate( } } -fun ExpressionConstraint.evaluate( +suspend fun ExpressionConstraint.evaluate( value: TypedInstance, schema: Schema, context: InPlaceQueryEngine diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/constraints/DefaultConstraintEvaluator.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/constraints/DefaultConstraintEvaluator.kt deleted file mode 100644 index 11a0097284..0000000000 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/constraints/DefaultConstraintEvaluator.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.orbitalhq.models.constraints - -import com.orbitalhq.models.InPlaceQueryEngine -import com.orbitalhq.models.TypedInstance -import com.orbitalhq.schemas.ConstraintEvaluation -import lang.taxi.services.operations.constraints.Constraint - -data class DefaultConstraintEvaluator( - val context: InPlaceQueryEngine -) : ConstraintEvaluator { - override fun evaluate(constraint: Constraint, value: TypedInstance): ConstraintEvaluation { - return constraint.evaluate(value, context.schema, context) - } -} diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/FunctionRegistry.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/FunctionRegistry.kt index 2893fe7d63..a670218a52 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/FunctionRegistry.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/FunctionRegistry.kt @@ -16,7 +16,7 @@ import mu.KotlinLogging class FunctionRegistry(private val invokers: List) { private val invokersByName = invokers.associateBy { it.functionName } - fun invoke( + suspend fun invoke( function: Function, declaredInputs: List, schema: Schema, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/Functions.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/Functions.kt index e5d1d0fa6c..71e90a1266 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/Functions.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/Functions.kt @@ -24,7 +24,7 @@ typealias FunctionHandler = ( ) -> TypedInstance interface FunctionInvoker { - fun invoke( + suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, @@ -59,7 +59,7 @@ interface SelfDescribingFunction : NamedFunctionInvoker { * Helper class which will return TypedNull if any of the provided arguments were null. */ abstract class NullSafeInvoker : NamedFunctionInvoker { - protected abstract fun doInvoke( + protected abstract suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -70,7 +70,7 @@ abstract class NullSafeInvoker : NamedFunctionInvoker { resultCache: MutableMap ): TypedInstance - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, @@ -141,7 +141,7 @@ class InlineFunctionInvoker(override val functionName: QualifiedName, val handle NullSafeInvoker() { constructor(functionName: String, handler: FunctionHandler) : this(QualifiedName.from(functionName), handler) - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/BaseMathFunction.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/BaseMathFunction.kt index 206f081b4a..29bdd629f3 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/BaseMathFunction.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/BaseMathFunction.kt @@ -20,7 +20,7 @@ import java.math.BigDecimal abstract class MathIteratingFunction : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Collections.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Collections.kt index e890c30bc0..c01e7c6420 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Collections.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Collections.kt @@ -61,7 +61,7 @@ abstract class BooleanPredicateEvaluator( ) : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -114,7 +114,7 @@ private fun expectAllBoolean( object Contains : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Contains.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -133,7 +133,7 @@ object Contains : NullSafeInvoker() { } object ContainsAll : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -161,7 +161,7 @@ object ContainsAll : NullSafeInvoker() { } object ContainsAny : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -197,7 +197,7 @@ object ContainsAny : NullSafeInvoker() { object Size : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -220,7 +220,7 @@ object Size : NullSafeInvoker() { object IsNullOrEmpty : NamedFunctionInvoker { override val functionName: QualifiedName = lang.taxi.functions.stdlib.IsNullOrEmpty.name - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/EnumFunctions.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/EnumFunctions.kt index 07fd7fffee..5938dc2655 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/EnumFunctions.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/EnumFunctions.kt @@ -28,7 +28,7 @@ object EnumFunctions { object EnumForName : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.EnumForName.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -68,7 +68,7 @@ object EnumForName : NullSafeInvoker() { object HasEnumNamed : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.HasEnumNamed.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Functional.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Functional.kt index d2333de185..1dfa96263b 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Functional.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Functional.kt @@ -35,7 +35,7 @@ object Functional { object Fold : NamedFunctionInvoker { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Fold.name - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, @@ -77,7 +77,7 @@ object MapFunction : NullSafeInvoker() { private val logger = KotlinLogging.logger {} - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -152,7 +152,7 @@ object MapFunction : NullSafeInvoker() { } object Reduce : NamedFunctionInvoker { - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/ObjectFunctions.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/ObjectFunctions.kt index 668bc83aab..2ec0244c1d 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/ObjectFunctions.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/ObjectFunctions.kt @@ -33,7 +33,7 @@ object ObjectFunctions { object CollectAllInstances : NullSafeInvoker() { private val logger = KotlinLogging.logger {} - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -69,7 +69,7 @@ object CollectAllInstances : NullSafeInvoker() { object Equals : NamedFunctionInvoker { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Equals.name - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, @@ -91,7 +91,7 @@ object Equals : NamedFunctionInvoker { object EmptyInstance : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Strings.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Strings.kt index dabeb7285b..f9bbc45e28 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Strings.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/Strings.kt @@ -45,7 +45,7 @@ object Strings { object Concat : NamedFunctionInvoker { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Concat.name - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, @@ -68,7 +68,7 @@ object Concat : NamedFunctionInvoker { object Trim : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Trim.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -113,7 +113,7 @@ private fun String.substringOrTypedNull( object Left : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Left.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -140,7 +140,7 @@ object Left : NullSafeInvoker() { object Right : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Right.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -167,7 +167,7 @@ object Right : NullSafeInvoker() { object Mid : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Mid.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -194,7 +194,7 @@ object Mid : NullSafeInvoker() { object Uppercase : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Uppercase.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -219,7 +219,7 @@ object Uppercase : NullSafeInvoker() { object Lowercase : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Lowercase.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -243,7 +243,7 @@ object Lowercase : NullSafeInvoker() { object Length : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Length.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -267,7 +267,7 @@ object Length : NullSafeInvoker() { object Find : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.IndexOf.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -290,7 +290,7 @@ object Find : NullSafeInvoker() { } object ContainsString : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -316,7 +316,7 @@ object ContainsString : NullSafeInvoker() { object Coalesce : NamedFunctionInvoker { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Coalesce.name - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, @@ -333,7 +333,7 @@ object Coalesce : NamedFunctionInvoker { object Replace : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Replace.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -359,7 +359,7 @@ object Replace : NullSafeInvoker() { } object PadStart : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -384,7 +384,7 @@ object PadStart : NullSafeInvoker() { object PadEnd : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -408,7 +408,7 @@ object PadEnd : NullSafeInvoker() { } object ApplyFormat : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -430,7 +430,7 @@ object ApplyFormat : NullSafeInvoker() { } object StartsWith : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -452,7 +452,7 @@ object StartsWith : NullSafeInvoker() { } object EndsWith : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -474,7 +474,7 @@ object EndsWith : NullSafeInvoker() { } object Matches : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, @@ -496,7 +496,7 @@ object Matches : NullSafeInvoker() { } object ContainsPattern : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Append.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Append.kt index 6d2ad94724..4376ea9188 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Append.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Append.kt @@ -13,7 +13,7 @@ import lang.taxi.types.FormatsAndZoneOffset import lang.taxi.types.QualifiedName object Append : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/CollectionFilteringFunction.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/CollectionFilteringFunction.kt index fa06da3b5c..68b4f1fc55 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/CollectionFilteringFunction.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/CollectionFilteringFunction.kt @@ -57,7 +57,7 @@ abstract class CollectionFilteringFunction : NullSafeInvoker() { return Triple(collection, deferredInstance, dataSource).right() } - protected fun applyFilter( + protected suspend fun applyFilter( inputValues: List, schema: Schema, returnType: Type, @@ -93,7 +93,7 @@ abstract class CollectionFilteringFunction : NullSafeInvoker() { } - protected fun evaluatePredicateAgainstMember( + protected suspend fun evaluatePredicateAgainstMember( collectionMember: TypedInstance, schema: Schema, objectFactory: EvaluationValueSupplier, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/CollectionPredicateFunctions.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/CollectionPredicateFunctions.kt index 4e1123d4de..6c8ecea5da 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/CollectionPredicateFunctions.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/CollectionPredicateFunctions.kt @@ -30,7 +30,7 @@ enum class CollectionOperationType( abstract class BaseCollectionPredicateInvoker(val operationType: CollectionOperationType) : CollectionFilteringFunction(), NamedFunctionInvoker { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Filter.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Filter.kt index d0b443c4a3..1391891fdc 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Filter.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Filter.kt @@ -18,7 +18,7 @@ import lang.taxi.types.QualifiedName object Filter : CollectionFilteringFunction() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Filter.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/FilterEach.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/FilterEach.kt index eb4eea5ad2..e414d01360 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/FilterEach.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/FilterEach.kt @@ -16,7 +16,7 @@ import lang.taxi.types.QualifiedName object FilterEach : CollectionFilteringFunction() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.FilterEach.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/First.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/First.kt index 4dd5ac5e0e..bd08d8b9c9 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/First.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/First.kt @@ -17,7 +17,7 @@ import lang.taxi.types.QualifiedName abstract class CollectionNavigatingFunction : NamedFunctionInvoker, CollectionFilteringFunction() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/IfEmpty.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/IfEmpty.kt index 87aacd2585..4bc5eb119d 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/IfEmpty.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/IfEmpty.kt @@ -16,7 +16,7 @@ object IfEmpty : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.IfEmpty.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/IndexOf.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/IndexOf.kt index aae5b19801..936ba5aa43 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/IndexOf.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/IndexOf.kt @@ -15,7 +15,7 @@ import lang.taxi.types.FormatsAndZoneOffset import lang.taxi.types.QualifiedName object IndexOf : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Intersection.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Intersection.kt index db02c6e312..3349a2d3be 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Intersection.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Intersection.kt @@ -33,7 +33,7 @@ object Intersection: NamedFunctionInvoker, CollectionFilteringFunction() { } } - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/JoinToString.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/JoinToString.kt index e678295dbc..d1c46f9e70 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/JoinToString.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/JoinToString.kt @@ -14,7 +14,7 @@ import lang.taxi.types.QualifiedName object JoinToString : NamedFunctionInvoker { override val functionName: QualifiedName = lang.taxi.functions.stdlib.JoinToString.name - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/ListOf.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/ListOf.kt index e24c879485..9c4f129ef7 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/ListOf.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/ListOf.kt @@ -17,7 +17,7 @@ import lang.taxi.types.QualifiedName object ListOf : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.ListOf.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/OrEmpty.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/OrEmpty.kt index b70bd3891d..d341e760c3 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/OrEmpty.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/OrEmpty.kt @@ -16,7 +16,7 @@ import lang.taxi.types.QualifiedName object OrEmpty : NamedFunctionInvoker { // Intentionally not NullSafeInvoker() as the first argument is often null override val functionName: QualifiedName = lang.taxi.functions.stdlib.OrEmpty.name - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Single.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Single.kt index f64c9736de..a17facbbbd 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Single.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/Single.kt @@ -16,7 +16,7 @@ import mu.KotlinLogging object Single : NamedFunctionInvoker, CollectionFilteringFunction() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Single.name private val logger = KotlinLogging.logger {} - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/SingleBy.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/SingleBy.kt index cde97cf339..7e401e9068 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/SingleBy.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/collections/SingleBy.kt @@ -15,7 +15,7 @@ import mu.KotlinLogging object SingleBy : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.SingleBy.name private val logger = KotlinLogging.logger {} - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/BaseDateMathFunction.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/BaseDateMathFunction.kt index 51bd4834b3..6ac8d07233 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/BaseDateMathFunction.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/BaseDateMathFunction.kt @@ -26,7 +26,7 @@ import java.time.temporal.TemporalAmount import java.time.temporal.TemporalUnit abstract class BaseDateMathFunction(private val unit: TemporalUnit) : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/Now.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/Now.kt index 28ba95b8cd..e8ed9a8f64 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/Now.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/Now.kt @@ -24,7 +24,7 @@ import java.time.LocalTime import java.time.temporal.Temporal abstract class BaseCurrentTimeInvoker(private val valueProvider: () -> Temporal) : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/ParseDate.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/ParseDate.kt index 40687f9cb0..43d34dd6a6 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/ParseDate.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/dates/ParseDate.kt @@ -16,7 +16,7 @@ import lang.taxi.types.PrimitiveType import lang.taxi.types.QualifiedName object ParseDate : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/errors/Throw.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/errors/Throw.kt index 7cb152b3d0..a8fa97e85c 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/errors/Throw.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/errors/Throw.kt @@ -16,7 +16,7 @@ import lang.taxi.types.QualifiedName object Throw : NamedFunctionInvoker { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Throw.name - override fun invoke( + override suspend fun invoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/math/Average.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/math/Average.kt index 1d2624d78d..17793a9650 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/math/Average.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/math/Average.kt @@ -19,7 +19,7 @@ import java.math.RoundingMode object Average : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.Average.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/math/Round.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/math/Round.kt index 18248e1432..e0e97e9190 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/math/Round.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/math/Round.kt @@ -15,7 +15,7 @@ import java.math.BigDecimal import java.math.RoundingMode object Round : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/transform/Convert.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/transform/Convert.kt index 28251af5b5..0ac570e2b7 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/transform/Convert.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/transform/Convert.kt @@ -14,7 +14,7 @@ import lang.taxi.types.QualifiedName import mu.KotlinLogging object Convert : NullSafeInvoker() { - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/transform/ToRawType.kt b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/transform/ToRawType.kt index 7490404ffc..dfb483bb3c 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/transform/ToRawType.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/models/functions/stdlib/transform/ToRawType.kt @@ -21,7 +21,7 @@ import lang.taxi.types.QualifiedName object ToRawType : NullSafeInvoker() { override val functionName: QualifiedName = lang.taxi.functions.stdlib.ToRawType.name - override fun doInvoke( + override suspend fun doInvoke( inputValues: List, schema: Schema, returnType: Type, diff --git a/vyne-core-types/src/main/java/com/orbitalhq/query/caching/AbstractMergingStateStore.kt b/vyne-core-types/src/main/java/com/orbitalhq/query/caching/AbstractMergingStateStore.kt index 272f75aead..7b5d2c0f8e 100644 --- a/vyne-core-types/src/main/java/com/orbitalhq/query/caching/AbstractMergingStateStore.kt +++ b/vyne-core-types/src/main/java/com/orbitalhq/query/caching/AbstractMergingStateStore.kt @@ -72,19 +72,21 @@ abstract class AbstractMergingStateStore( companion object { fun buildSumTypeFromValues(sumType: Type, values: List, schema: Schema): TypedInstance { - return TypedObjectFactory( - sumType, - FactBag.of(values, schema), - schema, - source = MixedSources, - // This is important. - // We take the last value when reading from a fact bag. - // More recent values overwrite older values - // This works down the tree - two different types with children fields of - // the same type will pick the more recently inserted - factBagSearchStrategy = FactDiscoveryStrategy.ANY_DEPTH_TAKE_LAST - ) - .build() + return kotlinx.coroutines.runBlocking { + TypedObjectFactory( + sumType, + FactBag.of(values, schema), + schema, + source = MixedSources, + // This is important. + // We take the last value when reading from a fact bag. + // More recent values overwrite older values + // This works down the tree - two different types with children fields of + // the same type will pick the more recently inserted + factBagSearchStrategy = FactDiscoveryStrategy.ANY_DEPTH_TAKE_LAST + ) + .build() + } } } diff --git a/vyne-csv-utils/pom.xml b/vyne-csv-utils/pom.xml index 2fccc6a29c..ddb1c145ab 100644 --- a/vyne-csv-utils/pom.xml +++ b/vyne-csv-utils/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -58,7 +58,7 @@ com.orbitalhq datatype-converters - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT test diff --git a/vyne-csv-utils/src/main/java/com/orbitalhq/formats/csv/CsvImporterUtil.kt b/vyne-csv-utils/src/main/java/com/orbitalhq/formats/csv/CsvImporterUtil.kt index 5a219e14bf..d163bcac58 100644 --- a/vyne-csv-utils/src/main/java/com/orbitalhq/formats/csv/CsvImporterUtil.kt +++ b/vyne-csv-utils/src/main/java/com/orbitalhq/formats/csv/CsvImporterUtil.kt @@ -33,15 +33,17 @@ object CsvImporterUtil { // .filter { parsed.headerNames == null || parsed.headerNames.isEmpty() || parsed.headerNames.size == it.size() } .map { csvRecord -> ParsedTypeInstance( - TypedObjectFactory( - targetType, - csvRecord, - schema, - nullValues, - source = Provided, - functionRegistry = functionRegistry, - formatSpecs = emptyList() - ).build() + kotlinx.coroutines.runBlocking { + TypedObjectFactory( + targetType, + csvRecord, + schema, + nullValues, + source = Provided, + functionRegistry = functionRegistry, + formatSpecs = emptyList() + ).build() + } ) } return records diff --git a/vyne-history-core/pom.xml b/vyne-history-core/pom.xml index 200936870f..14fc4109aa 100644 --- a/vyne-history-core/pom.xml +++ b/vyne-history-core/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/vyne-query-api/pom.xml b/vyne-query-api/pom.xml index f36840463e..5133172d19 100644 --- a/vyne-query-api/pom.xml +++ b/vyne-query-api/pom.xml @@ -4,7 +4,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/vyne-query-service/pom.xml b/vyne-query-service/pom.xml index a724f55d59..2dfb0dcc34 100644 --- a/vyne-query-service/pom.xml +++ b/vyne-query-service/pom.xml @@ -4,7 +4,7 @@ com.orbitalhq platform - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 @@ -330,11 +330,11 @@ 20231013 test - - com.orbitalhq - test-cli - ${project.version} - + + + + + org.jetbrains.kotlinx diff --git a/vyne-search/pom.xml b/vyne-search/pom.xml index 107df34b35..1995d6c770 100644 --- a/vyne-search/pom.xml +++ b/vyne-search/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/vyne-spring-http-client/pom.xml b/vyne-spring-http-client/pom.xml index cd1bce1525..9a3bb25d81 100644 --- a/vyne-spring-http-client/pom.xml +++ b/vyne-spring-http-client/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/vyne-spring-http/pom.xml b/vyne-spring-http/pom.xml index 40f734569e..d04d8aa332 100644 --- a/vyne-spring-http/pom.xml +++ b/vyne-spring-http/pom.xml @@ -5,7 +5,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0 diff --git a/vyne-spring/pom.xml b/vyne-spring/pom.xml index 42dfa1425b..570f8ba0ab 100644 --- a/vyne-spring/pom.xml +++ b/vyne-spring/pom.xml @@ -3,7 +3,7 @@ platform com.orbitalhq - 0.37.0-SNAPSHOT + d0.38.0-SNAPSHOT 4.0.0