Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Fix #2165] Adding custom mutations #2166

Merged
merged 6 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .rat-excludes
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ application.properties
basic.schema.graphqls
# data-index/data-index-service/data-index-service-common/src/main/resources/domain.schema.graphqls
domain.schema.graphqls
# /data-index/data-index-mutations/data-index-shared-output-mutation/src/main/resources/mutation.schema.graphqls
mutation.schema.graphqls
# data-index/kogito-addons-quarkus-data-index/kogito-addons-quarkus-data-index-infinispan/integration-tests-process/src/main/resources/hello.bpmn
hello.bpmn
# data-index/kogito-addons-quarkus-data-index/kogito-addons-quarkus-data-index-infinispan/integration-tests-process/src/main/resources/META-INF/processSVG/hello.svg
Expand Down Expand Up @@ -97,4 +99,4 @@ application.properties
# jobs-service/kogito-addons-jobs-service/kogito-addons-quarkus-jobs-service-embedded/runtime/src/main/resources/META-INF/services/org.eclipse.microprofile.config.spi.ConfigSource
org.eclipse.microprofile.config.spi.ConfigSource
# trusty/trusty-service/trusty-service-common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
org.mockito.plugins.MockMaker
org.mockito.plugins.MockMaker
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,56 @@
*/
package org.kie.kogito.index;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;

public class CommonUtils {

public static final int ERROR_STATE = 5;
private static final Set<String> finalStates = Set.of("Completed", "Aborted");
private static final Logger logger = LoggerFactory.getLogger(CommonUtils.class);
fjtirado marked this conversation as resolved.
Show resolved Hide resolved

public static boolean isTaskCompleted(String status) {
return finalStates.contains(status);
}

public static String getServiceUrl(String endpoint, String processId) {
logger.debug("Process endpoint {}", endpoint);
if (endpoint == null) {
return null;
}
if (endpoint.startsWith("/")) {
logger.warn("Process '{}' endpoint '{}', does not contain full URL, please review the kogito.service.url system property to point the public URL for this runtime.",
processId, endpoint);
}
String context = getContext(processId);
logger.debug("Process context {}", context);
if (context.equals(endpoint) || endpoint.equals("/" + context)) {
return null;
} else {
return endpoint.contains("/" + context) ? endpoint.substring(0, endpoint.lastIndexOf("/" + context)) : null;
}
}

public static TypeDefinitionRegistry loadSchemaDefinitionFile(String fileName) {
SchemaParser schemaParser = new SchemaParser();
try (InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
InputStreamReader reader = new InputStreamReader(stream)) {
return schemaParser.parse(reader);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private static String getContext(String processId) {
return processId != null && processId.contains(".") ? processId.substring(processId.lastIndexOf('.') + 1) : processId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.kie.kogito.index.api;

import com.fasterxml.jackson.databind.JsonNode;

public record ExecuteArgs(JsonNode input, String businessKey, String referenceId) {

public static ExecuteArgs of(JsonNode input) {
return builder().withInput(input).build();
}

public static Builder builder() {
return new Builder();
}

public static class Builder {

private JsonNode input;
private String businessKey;
private String referenceId;

private Builder() {
}

public Builder withInput(JsonNode input) {
this.input = input;
return this;
}

public Builder withBusinessKey(String businessKey) {
this.businessKey = businessKey;
return this;
}

public Builder withReferenceId(String referenceId) {
this.referenceId = referenceId;
return this;
}

public ExecuteArgs build() {
return new ExecuteArgs(input, businessKey, referenceId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@

import org.kie.kogito.index.model.Job;
import org.kie.kogito.index.model.Node;
import org.kie.kogito.index.model.ProcessDefinition;
import org.kie.kogito.index.model.ProcessInstance;
import org.kie.kogito.index.model.UserTaskInstance;

public interface KogitoRuntimeClient {

CompletableFuture<String> executeProcessIntance(ProcessDefinition definition, ExecuteArgs args);

CompletableFuture<String> abortProcessInstance(String serviceURL, ProcessInstance processInstance);

CompletableFuture<String> retryProcessInstance(String serviceURL, ProcessInstance processInstance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@
*/
package org.kie.kogito.index.graphql;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.ServiceLoader;
import java.util.ServiceLoader.Provider;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.kie.kogito.index.CommonUtils;
import org.kie.kogito.index.api.KogitoRuntimeClient;
import org.kie.kogito.index.graphql.query.GraphQLQueryOrderByParser;
import org.kie.kogito.index.graphql.query.GraphQLQueryParserRegistry;
Expand All @@ -44,13 +45,14 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import graphql.schema.GraphQLInputObjectType;
import graphql.schema.GraphQLNamedType;
import graphql.schema.GraphQLScalarType;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;
import graphql.schema.idl.TypeRuntimeWiring.Builder;
import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;

Expand Down Expand Up @@ -82,8 +84,12 @@ public abstract class AbstractGraphQLSchemaManager implements GraphQLSchemaManag

private GraphQLSchema schema;

private Collection<GraphQLMutationsProvider> mutations;

@PostConstruct
public void setup() {
mutations = ServiceLoader.load(GraphQLMutationsProvider.class).stream().map(Provider::get).collect(Collectors.toList());

schema = createSchema();
GraphQLQueryParserRegistry.get().registerParsers(
(GraphQLInputObjectType) schema.getType("ProcessDefinitionArgument"),
Expand All @@ -92,14 +98,19 @@ public void setup() {
(GraphQLInputObjectType) schema.getType("JobArgument"));
}

protected final void loadAdditionalMutations(Builder builder) {
Map<String, DataFetcher<CompletableFuture<?>>> mutationMap = mutations.stream().map(m -> m.mutations(this)).flatMap(map -> map.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2));
LOGGER.info("Custom mutations are {}", mutationMap);
mutationMap.forEach(builder::dataFetcher);
}

protected final void loadAdditionalMutations(TypeDefinitionRegistry typeRegistry) {
mutations.stream().map(GraphQLMutationsProvider::registry).forEach(typeRegistry::merge);
}

protected TypeDefinitionRegistry loadSchemaDefinitionFile(String fileName) {
SchemaParser schemaParser = new SchemaParser();
try (InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
InputStreamReader reader = new InputStreamReader(stream)) {
return schemaParser.parse(reader);
} catch (IOException e) {
throw new RuntimeException(e);
}
return CommonUtils.loadSchemaDefinitionFile(fileName);
}

public abstract GraphQLSchema createSchema();
Expand Down Expand Up @@ -142,25 +153,7 @@ public ProcessDefinition getProcessDefinition(DataFetchingEnvironment env) {
}

protected String getServiceUrl(String endpoint, String processId) {
LOGGER.debug("Process endpoint {}", endpoint);
if (endpoint == null) {
return null;
}
if (endpoint.startsWith("/")) {
LOGGER.warn("Process '{}' endpoint '{}', does not contain full URL, please review the kogito.service.url system property to point the public URL for this runtime.",
processId, endpoint);
}
String context = getContext(processId);
LOGGER.debug("Process context {}", context);
if (context.equals(endpoint) || endpoint.equals("/" + context)) {
return null;
} else {
return endpoint.contains("/" + context) ? endpoint.substring(0, endpoint.lastIndexOf("/" + context)) : null;
}
}

private String getContext(String processId) {
return processId != null && processId.contains(".") ? processId.substring(processId.lastIndexOf('.') + 1) : processId;
return CommonUtils.getServiceUrl(endpoint, processId);
}

protected Collection<ProcessInstance> getChildProcessInstancesValues(DataFetchingEnvironment env) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.kie.kogito.index.graphql;

import java.util.Map;
import java.util.concurrent.CompletableFuture;

import graphql.schema.DataFetcher;
import graphql.schema.idl.TypeDefinitionRegistry;

public interface GraphQLMutationsProvider {
Map<String, DataFetcher<CompletableFuture<?>>> mutations(AbstractGraphQLSchemaManager schemaManager);

TypeDefinitionRegistry registry();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!--

Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.

-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.kie.kogito</groupId>
<artifactId>data-index-mutations</artifactId>
<version>999-SNAPSHOT</version>
</parent>
<artifactId>data-index-shared-output-mutation</artifactId>
<dependencies>
<dependency>
<groupId>org.kie.kogito</groupId>
<artifactId>data-index-graphql</artifactId>
</dependency>
</dependencies>
<properties>
<java.module.name>org.kie.kogito.index.service.mutations</java.module.name>
</properties>
</project>
Loading
Loading