diff --git a/.github/workflows/intgtest.yml b/.github/workflows/intgtest.yml index bd3312bb..642420d8 100644 --- a/.github/workflows/intgtest.yml +++ b/.github/workflows/intgtest.yml @@ -1,6 +1,13 @@ -name: Integration Tests +name: CI -on: workflow_dispatch +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: jobs: integration-test: @@ -18,7 +25,7 @@ jobs: run: | hostname echo "host is $HOSTNAME" - ./gradlew clean test -x check + ./gradlew clean test env: SDK_INTEGRATION_TESTS_SERVER_API_URL: ${{ secrets.SDK_INTEGRATION_TESTS_SERVER_API_URL }} SDK_INTEGRATION_TESTS_SERVER_KEY_ID: ${{ secrets.SDK_INTEGRATION_TESTS_SERVER_KEY_ID }} diff --git a/build.gradle b/build.gradle index 2b9e4ad6..f5f7125d 100644 --- a/build.gradle +++ b/build.gradle @@ -20,9 +20,8 @@ ext { versions = [ awaitility : '4.2.0', commonsLang : '3.12.0', - conductor : '3.9.0-orkes-o', + conductor : '3.9.12-orkes', jackson : '2.11.4!!', - jersey : '1.19.4', junit : '5.9.0', slf4j : '1.7.36', spectator : '1.3.7', @@ -33,10 +32,10 @@ ext { wiremock : '2.33.2', ioGRPC : '1.49.0', ioGRPC : '1.49.0', - protoBuf : '3.19.4', + protoBuf : '3.19.4', lombok : '1.18.24', - revJAXRS : '2.1.1', - revJerseyCommon : '2.22.2', + revJAXRS : '2.1.1', + log4j : '2.17.1', netty : '4.1.77.Final' ] @@ -46,20 +45,13 @@ group = 'io.orkes.conductor' dependencies { - api ("io.orkes.conductor:conductor-client:${versions.conductor}") - api ("io.orkes.conductor:conductor-client-spring:${versions.conductor}") api ("io.orkes.conductor:conductor-common:${versions.conductor}") api ("io.orkes.conductor:conductor-grpc:${versions.conductor}") api ("io.orkes.conductor:conductor-java-sdk:${versions.conductor}") - implementation "com.sun.jersey:jersey-client:${versions.jersey}" implementation 'javax.annotation:javax.annotation-api:1.3.2' implementation "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:${versions.jackson}" implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${versions.jackson}" - - implementation "javax.ws.rs:javax.ws.rs-api:${versions.revJAXRS}" - implementation "org.glassfish.jersey.core:jersey-common:${versions.revJerseyCommon}" - implementation "org.slf4j:slf4j-api:${versions.slf4j}" api 'io.orkes.conductor:orkes-conductor-common-protos:0.9.2' @@ -89,9 +81,6 @@ dependencies { implementation 'com.squareup.okhttp:okhttp:2.7.5' implementation 'com.squareup.okhttp:logging-interceptor:2.7.5' - implementation 'com.google.code.gson:gson:2.9.0' - implementation 'io.gsonfire:gson-fire:1.8.5' - implementation 'io.swagger.core.v3:swagger-annotations:2.2.2' implementation "org.apache.commons:commons-lang3:${versions.commonsLang}" @@ -103,6 +92,17 @@ dependencies { implementation "com.azure:azure-security-keyvault-secrets:${versions.azureSsm}" implementation "com.azure:azure-identity:${versions.azureIdentity}" + //logging + implementation "org.apache.logging.log4j:log4j-core:${versions.log4j}!!" + implementation "org.apache.logging.log4j:log4j-api:${versions.log4j}!!" + implementation "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}!!" + implementation "org.apache.logging.log4j:log4j-jul:${versions.log4j}!!" + implementation "org.apache.logging.log4j:log4j-web:${versions.log4j}!!" + //implementation "org.apache.logging.log4j:log4j-to-slf4j:${versions.log4j}!!" + + //spring + implementation "org.springframework:spring-context:5.3.24" + annotationProcessor "org.projectlombok:lombok:${versions.lombok}" testAnnotationProcessor "org.projectlombok:lombok:${versions.lombok}" @@ -114,6 +114,11 @@ dependencies { testImplementation 'org.testcontainers:testcontainers:1.17.1' testImplementation 'com.amazonaws:aws-java-sdk-core:1.12.138' testCompileOnly "org.projectlombok:lombok:${versions.lombok}" + + //Spring + testImplementation 'org.springframework.boot:spring-boot-starters:2.2.13.RELEASE' + testImplementation 'org.springframework.boot:spring-boot-autoconfigure:2.7.8' + testImplementation 'org.springframework.boot:spring-boot-test:2.7.8' } repositories { @@ -206,6 +211,14 @@ configurations.implementation { exclude(group : "com.netflix.conductor") } +configurations { + all { + //exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl' + exclude group: 'org.slf4j', module: 'slf4j-log4j12' + exclude group: 'com.netflix.conductor' + exclude group: 'javax.ws.rs', module: 'javax.ws.rs-api' + } +} spotless { java { @@ -231,7 +244,7 @@ signing { } } tasks.withType(Test) { - maxParallelForks = 1 + maxParallelForks = 10 } sourceSets.main.java.srcDirs += ['example/java', 'example/resources'] diff --git a/gradle.properties b/gradle.properties index 024c2a35..e997a9af 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=3.0.45 \ No newline at end of file +version=2.0.0 \ No newline at end of file diff --git a/src/main/java/com/google/gson/annotations/SerializedName.java b/src/main/java/com/google/gson/annotations/SerializedName.java new file mode 100644 index 00000000..c3ac7d8c --- /dev/null +++ b/src/main/java/com/google/gson/annotations/SerializedName.java @@ -0,0 +1,17 @@ +/* + * Copyright 2023 Orkes, Inc. + *

+ * Licensed 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 com.google.gson.annotations; + +public @interface SerializedName { + String value(); +} diff --git a/src/main/java/com/netflix/conductor/client/config/ConductorClientConfiguration.java b/src/main/java/com/netflix/conductor/client/config/ConductorClientConfiguration.java new file mode 100644 index 00000000..0aaad6fb --- /dev/null +++ b/src/main/java/com/netflix/conductor/client/config/ConductorClientConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Orkes, Inc. + *

+ * Licensed 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 com.netflix.conductor.client.config; + +public interface ConductorClientConfiguration { + + /** + * @return the workflow input payload size threshold in KB, beyond which the payload will be + * processed based on {@link + * ConductorClientConfiguration#isExternalPayloadStorageEnabled()}. + */ + int getWorkflowInputPayloadThresholdKB(); + + /** + * @return the max value of workflow input payload size threshold in KB, beyond which the + * payload will be rejected regardless external payload storage is enabled. + */ + int getWorkflowInputMaxPayloadThresholdKB(); + + /** + * @return the task output payload size threshold in KB, beyond which the payload will be + * processed based on {@link + * ConductorClientConfiguration#isExternalPayloadStorageEnabled()}. + */ + int getTaskOutputPayloadThresholdKB(); + + /** + * @return the max value of task output payload size threshold in KB, beyond which the payload + * will be rejected regardless external payload storage is enabled. + */ + int getTaskOutputMaxPayloadThresholdKB(); + + /** + * @return the flag which controls the use of external storage for storing workflow/task input + * and output JSON payloads with size greater than threshold. If it is set to true, the + * payload is stored in external location. If it is set to false, the payload is rejected + * and the task/workflow execution fails. + */ + boolean isExternalPayloadStorageEnabled(); +} diff --git a/src/main/java/com/netflix/conductor/client/config/PropertyFactory.java b/src/main/java/com/netflix/conductor/client/config/PropertyFactory.java new file mode 100644 index 00000000..79d4a510 --- /dev/null +++ b/src/main/java/com/netflix/conductor/client/config/PropertyFactory.java @@ -0,0 +1,91 @@ +/* + * Copyright 2020 Orkes, Inc. + *

+ * Licensed 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 com.netflix.conductor.client.config; + +import java.util.concurrent.ConcurrentHashMap; + +import com.netflix.config.DynamicProperty; + +/** Used to configure the Conductor workers using properties. */ +public class PropertyFactory { + + private final DynamicProperty global; + private final DynamicProperty local; + + private static final String PROPERTY_PREFIX = "conductor.worker"; + + private static final ConcurrentHashMap PROPERTY_FACTORY_MAP = + new ConcurrentHashMap<>(); + + private PropertyFactory(String prefix, String propName, String workerName) { + this.global = DynamicProperty.getInstance(prefix + "." + propName); + this.local = DynamicProperty.getInstance(prefix + "." + workerName + "." + propName); + } + + /** + * @param defaultValue Default Value + * @return Returns the value as integer. If not value is set (either global or worker specific), + * then returns the default value. + */ + public Integer getInteger(int defaultValue) { + Integer value = local.getInteger(); + if (value == null) { + value = global.getInteger(defaultValue); + } + return value; + } + + /** + * @param defaultValue Default Value + * @return Returns the value as String. If not value is set (either global or worker specific), + * then returns the default value. + */ + public String getString(String defaultValue) { + String value = local.getString(); + if (value == null) { + value = global.getString(defaultValue); + } + return value; + } + + /** + * @param defaultValue Default Value + * @return Returns the value as Boolean. If not value is set (either global or worker specific), + * then returns the default value. + */ + public Boolean getBoolean(Boolean defaultValue) { + Boolean value = local.getBoolean(); + if (value == null) { + value = global.getBoolean(defaultValue); + } + return value; + } + + public static Integer getInteger(String workerName, String property, Integer defaultValue) { + return getPropertyFactory(workerName, property).getInteger(defaultValue); + } + + public static Boolean getBoolean(String workerName, String property, Boolean defaultValue) { + return getPropertyFactory(workerName, property).getBoolean(defaultValue); + } + + public static String getString(String workerName, String property, String defaultValue) { + return getPropertyFactory(workerName, property).getString(defaultValue); + } + + private static PropertyFactory getPropertyFactory(String workerName, String property) { + String key = property + "." + workerName; + return PROPERTY_FACTORY_MAP.computeIfAbsent( + key, t -> new PropertyFactory(PROPERTY_PREFIX, property, workerName)); + } +} diff --git a/src/main/java/com/netflix/conductor/client/exception/ConductorClientException.java b/src/main/java/com/netflix/conductor/client/exception/ConductorClientException.java new file mode 100644 index 00000000..2dc7c941 --- /dev/null +++ b/src/main/java/com/netflix/conductor/client/exception/ConductorClientException.java @@ -0,0 +1,140 @@ +/* + * Copyright 2020 Orkes, Inc. + *

+ * Licensed 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 com.netflix.conductor.client.exception; + +import java.util.List; + +import com.netflix.conductor.common.validation.ErrorResponse; +import com.netflix.conductor.common.validation.ValidationError; + +/** Client exception thrown from Conductor api clients. */ +public class ConductorClientException extends RuntimeException { + + private int status; + private String message; + private String instance; + private String code; + private boolean retryable; + + public List getValidationErrors() { + return validationErrors; + } + + public void setValidationErrors(List validationErrors) { + this.validationErrors = validationErrors; + } + + private List validationErrors; + + public ConductorClientException() { + super(); + } + + public ConductorClientException(String message) { + super(message); + this.message = message; + } + + public ConductorClientException(String message, Throwable cause) { + super(message, cause); + this.message = message; + } + + public ConductorClientException(int status, String message) { + super(message); + this.status = status; + this.message = message; + } + + public ConductorClientException(int status, ErrorResponse errorResponse) { + super(errorResponse.getMessage()); + this.status = status; + this.retryable = errorResponse.isRetryable(); + this.message = errorResponse.getMessage(); + this.code = errorResponse.getCode(); + this.instance = errorResponse.getInstance(); + this.validationErrors = errorResponse.getValidationErrors(); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + + builder.append(getClass().getName()).append(": "); + + if (this.message != null) { + builder.append(message); + } + + if (status > 0) { + builder.append(" {status=").append(status); + if (this.code != null) { + builder.append(", code='").append(code).append("'"); + } + + builder.append(", retryable: ").append(retryable); + } + + if (this.instance != null) { + builder.append(", instance: ").append(instance); + } + + if (this.validationErrors != null) { + builder.append(", validationErrors: ").append(validationErrors.toString()); + } + + builder.append("}"); + return builder.toString(); + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public void setStatus(int status) { + this.status = status; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public boolean isRetryable() { + return retryable; + } + + public void setRetryable(boolean retryable) { + this.retryable = retryable; + } + + @Override + public String getMessage() { + return this.message; + } + + public int getStatus() { + return this.status; + } +} diff --git a/src/main/java/com/netflix/conductor/client/http/EventClient.java b/src/main/java/com/netflix/conductor/client/http/EventClient.java new file mode 100644 index 00000000..00c12d82 --- /dev/null +++ b/src/main/java/com/netflix/conductor/client/http/EventClient.java @@ -0,0 +1,55 @@ +/* + * Copyright 2022 Orkes, Inc. + *

+ * Licensed 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 com.netflix.conductor.client.http; + +import java.util.List; + +import com.netflix.conductor.common.metadata.events.EventHandler; + +// Client class for all Event Handler operations +public abstract class EventClient{ + + /** Creates a default metadata client */ + public EventClient() { + } + + + + /** + * Register an event handler with the server. + * + * @param eventHandler the eventHandler definition. + */ + public abstract void registerEventHandler(EventHandler eventHandler); + + /** + * Updates an event handler with the server. + * + * @param eventHandler the eventHandler definition. + */ + public abstract void updateEventHandler(EventHandler eventHandler); + + /** + * @param event name of the event. + * @param activeOnly if true, returns only the active handlers. + * @return Returns the list of all the event handlers for a given event. + */ + public abstract List getEventHandlers(String event, boolean activeOnly); + + /** + * Removes the event handler definition from the conductor server + * + * @param name the name of the event handler to be unregistered + */ + public abstract void unregisterEventHandler(String name); +} diff --git a/src/main/java/com/netflix/conductor/client/http/MetadataClient.java b/src/main/java/com/netflix/conductor/client/http/MetadataClient.java new file mode 100644 index 00000000..87947959 --- /dev/null +++ b/src/main/java/com/netflix/conductor/client/http/MetadataClient.java @@ -0,0 +1,98 @@ +/* + * Copyright 2020 Orkes, Inc. + *

+ * Licensed 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 com.netflix.conductor.client.http; + +import java.util.List; + +import com.netflix.conductor.common.metadata.tasks.TaskDef; +import com.netflix.conductor.common.metadata.workflow.WorkflowDef; + +public abstract class MetadataClient { + + /** Creates a default metadata client */ + public MetadataClient() { + + } + + + // Workflow Metadata Operations + + /** + * Register a workflow definition with the server + * + * @param workflowDef the workflow definition + */ + public abstract void registerWorkflowDef(WorkflowDef workflowDef); + + /** + * Updates a list of existing workflow definitions + * + * @param workflowDefs List of workflow definitions to be updated + */ + public abstract void updateWorkflowDefs(List workflowDefs); + + /** + * Retrieve the workflow definition + * + * @param name the name of the workflow + * @param version the version of the workflow def + * @return Workflow definition for the given workflow and version + */ + public abstract WorkflowDef getWorkflowDef(String name, Integer version); + + /** + * Removes the workflow definition of a workflow from the conductor server. It does not remove + * associated workflows. Use with caution. + * + * @param name Name of the workflow to be unregistered. + * @param version Version of the workflow definition to be unregistered. + */ + public abstract void unregisterWorkflowDef(String name, Integer version); + + // Task Metadata Operations + + /** + * Registers a list of task types with the conductor server + * + * @param taskDefs List of task types to be registered. + */ + public abstract void registerTaskDefs(List taskDefs); + + /** + * Updates an existing task definition + * + * @param taskDef the task definition to be updated + */ + public abstract void updateTaskDef(TaskDef taskDef); + + /** + * Retrieve the task definition of a given task type + * + * @param taskType type of task for which to retrieve the definition + * @return Task Definition for the given task type + */ + public abstract TaskDef getTaskDef(String taskType); + + /** + * Removes the task definition of a task type from the conductor server. Use with caution. + * + * @param taskType Task type to be unregistered. + */ + public abstract void unregisterTaskDef(String taskType); + + /** + * + * @return All the registered task definitions + */ + public abstract List getAllTaskDefs(); +} diff --git a/src/main/java/com/netflix/conductor/client/http/TaskClient.java b/src/main/java/com/netflix/conductor/client/http/TaskClient.java new file mode 100644 index 00000000..84cdec8e --- /dev/null +++ b/src/main/java/com/netflix/conductor/client/http/TaskClient.java @@ -0,0 +1,204 @@ +/* + * Copyright 2022 Orkes, Inc. + *

+ * Licensed 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 com.netflix.conductor.client.http; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import com.netflix.conductor.common.metadata.tasks.PollData; +import com.netflix.conductor.common.metadata.tasks.Task; +import com.netflix.conductor.common.metadata.tasks.TaskExecLog; +import com.netflix.conductor.common.metadata.tasks.TaskResult; +import com.netflix.conductor.common.run.SearchResult; +import com.netflix.conductor.common.run.TaskSummary; +import com.netflix.conductor.common.utils.ExternalPayloadStorage; + +/** Client for conductor task management including polling for task, updating task status etc. */ +public abstract class TaskClient { + + + + /** Creates a default task client */ + public TaskClient() { + + } + + /** + * Perform a poll for a task of a specific task type. + * + * @param taskType The taskType to poll for + * @param domain The domain of the task type + * @param workerId Name of the client worker. Used for logging. + * @return Task waiting to be executed. + */ + public abstract Task pollTask(String taskType, String workerId, String domain); + /** + * Perform a batch poll for tasks by task type. Batch size is configurable by count. + * + * @param taskType Type of task to poll for + * @param workerId Name of the client worker. Used for logging. + * @param count Maximum number of tasks to be returned. Actual number of tasks returned can be + * less than this number. + * @param timeoutInMillisecond Long poll wait timeout. + * @return List of tasks awaiting to be executed. + */ + public abstract List batchPollTasksByTaskType( + String taskType, String workerId, int count, int timeoutInMillisecond); + + /** + * Batch poll for tasks in a domain. Batch size is configurable by count. + * + * @param taskType Type of task to poll for + * @param domain The domain of the task type + * @param workerId Name of the client worker. Used for logging. + * @param count Maximum number of tasks to be returned. Actual number of tasks returned can be + * less than this number. + * @param timeoutInMillisecond Long poll wait timeout. + * @return List of tasks awaiting to be executed. + */ + public abstract List batchPollTasksInDomain( + String taskType, String domain, String workerId, int count, int timeoutInMillisecond); + + /** + + + /** + * Updates the result of a task execution. If the size of the task output payload is bigger than + * {@link ExternalPayloadStorage}, if enabled, else the task is marked as + * FAILED_WITH_TERMINAL_ERROR. + * + * @param taskResult the {@link TaskResult} of the executed task to be updated. + */ + public abstract void updateTask(TaskResult taskResult); + + public abstract Optional evaluateAndUploadLargePayload( + Map taskOutputData, String taskType); + + /** + * Ack for the task poll. + * + * @param taskId Id of the task to be polled + * @param workerId user identified worker. + * @return true if the task was found with the given ID and acknowledged. False otherwise. If + * the server returns false, the client should NOT attempt to ack again. + */ + public abstract Boolean ack(String taskId, String workerId); + + /** + * Log execution messages for a task. + * + * @param taskId id of the task + * @param logMessage the message to be logged + */ + public abstract void logMessageForTask(String taskId, String logMessage); + + /** + * Fetch execution logs for a task. + * + * @param taskId id of the task. + */ + public abstract List getTaskLogs(String taskId); + + /** + * Retrieve information about the task + * + * @param taskId ID of the task + * @return Task details + */ + public abstract Task getTaskDetails(String taskId); + + /** + * Removes a task from a taskType queue + * + * @param taskType the taskType to identify the queue + * @param taskId the id of the task to be removed + */ + public abstract void removeTaskFromQueue(String taskType, String taskId); + + public abstract int getQueueSizeForTask(String taskType); + + public abstract int getQueueSizeForTask( + String taskType, String domain, String isolationGroupId, String executionNamespace); + + /** + * Get last poll data for a given task type + * + * @param taskType the task type for which poll data is to be fetched + * @return returns the list of poll data for the task type + */ + public abstract List getPollData(String taskType); + + /** + * Get the last poll data for all task types + * + * @return returns a list of poll data for all task types + */ + public abstract List getAllPollData(); + + /** + * Requeue pending tasks for all running workflows + * + * @return returns the number of tasks that have been requeued + */ + public abstract String requeueAllPendingTasks(); + + /** + * Requeue pending tasks of a specific task type + * + * @return returns the number of tasks that have been requeued + */ + public abstract String requeuePendingTasksByTaskType(String taskType); + /** + * Search for tasks based on payload + * + * @param query the search string + * @return returns the {@link SearchResult} containing the {@link TaskSummary} matching the + * query + */ + public abstract SearchResult search(String query); + + /** + * Search for tasks based on payload + * + * @param query the search string + * @return returns the {@link SearchResult} containing the {@link Task} matching the query + */ + public abstract SearchResult searchV2(String query); + + /** + * Paginated search for tasks based on payload + * + * @param start start value of page + * @param size number of tasks to be returned + * @param sort sort order + * @param freeText additional free text query + * @param query the search query + * @return the {@link SearchResult} containing the {@link TaskSummary} that match the query + */ + public abstract SearchResult search( + Integer start, Integer size, String sort, String freeText, String query); + + /** + * Paginated search for tasks based on payload + * + * @param start start value of page + * @param size number of tasks to be returned + * @param sort sort order + * @param freeText additional free text query + * @param query the search query + * @return the {@link SearchResult} containing the {@link Task} that match the query + */ + public abstract SearchResult searchV2( + Integer start, Integer size, String sort, String freeText, String query); +} diff --git a/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java b/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java new file mode 100644 index 00000000..914c08a9 --- /dev/null +++ b/src/main/java/com/netflix/conductor/client/http/WorkflowClient.java @@ -0,0 +1,216 @@ +/* + * Copyright 2021 Orkes, Inc. + *

+ * Licensed 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 com.netflix.conductor.client.http; + +import java.util.List; + +import com.netflix.conductor.common.metadata.workflow.RerunWorkflowRequest; +import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest; +import com.netflix.conductor.common.model.BulkResponse; +import com.netflix.conductor.common.run.SearchResult; +import com.netflix.conductor.common.run.Workflow; +import com.netflix.conductor.common.run.WorkflowSummary; +import com.netflix.conductor.common.run.WorkflowTestRequest; +import com.netflix.conductor.common.utils.ExternalPayloadStorage; + +public abstract class WorkflowClient { + + /** Creates a default workflow client */ + public WorkflowClient() { + + } + + + + /** + * Starts a workflow. If the size of the workflow input payload is bigger than {@link + * ExternalPayloadStorage}, if enabled, else the workflow is rejected. + * + * @param startWorkflowRequest the {@link StartWorkflowRequest} object to start the workflow + * @return the id of the workflow instance that can be used for tracking + */ + public abstract String startWorkflow(StartWorkflowRequest startWorkflowRequest); + + /** + * Retrieve a workflow by workflow id + * + * @param workflowId the id of the workflow + * @param includeTasks specify if the tasks in the workflow need to be returned + * @return the requested workflow + */ + public abstract Workflow getWorkflow(String workflowId, boolean includeTasks); + + /** + * Retrieve all workflows for a given correlation id and name + * + * @param name the name of the workflow + * @param correlationId the correlation id + * @param includeClosed specify if all workflows are to be returned or only running workflows + * @param includeTasks specify if the tasks in the workflow need to be returned + * @return list of workflows for the given correlation id and name + */ + public abstract List getWorkflows( + String name, String correlationId, boolean includeClosed, boolean includeTasks); + + + /** + * Removes a workflow from the system + * + * @param workflowId the id of the workflow to be deleted + * @param archiveWorkflow flag to indicate if the workflow should be archived before deletion + */ + public abstract void deleteWorkflow(String workflowId, boolean archiveWorkflow); + + /** + * Terminates the execution of all given workflows instances + * + * @param workflowIds the ids of the workflows to be terminated + * @param reason the reason to be logged and displayed + * @return the {@link BulkResponse} contains bulkErrorResults and bulkSuccessfulResults + */ + public abstract BulkResponse terminateWorkflows(List workflowIds, String reason); + + /** + * Retrieve all running workflow instances for a given name and version + * + * @param workflowName the name of the workflow + * @param version the version of the wokflow definition. Defaults to 1. + * @return the list of running workflow instances + */ + public abstract List getRunningWorkflow(String workflowName, Integer version); + + /** + * Retrieve all workflow instances for a given workflow name between a specific time period + * + * @param workflowName the name of the workflow + * @param version the version of the workflow definition. Defaults to 1. + * @param startTime the start time of the period + * @param endTime the end time of the period + * @return returns a list of workflows created during the specified during the time period + */ + public abstract List getWorkflowsByTimePeriod( + String workflowName, int version, Long startTime, Long endTime); + + /** + * Starts the decision task for the given workflow instance + * + * @param workflowId the id of the workflow instance + */ + public abstract void runDecider(String workflowId); + + /** + * Pause a workflow by workflow id + * + * @param workflowId the workflow id of the workflow to be paused + */ + public abstract void pauseWorkflow(String workflowId); + + /** + * Resume a paused workflow by workflow id + * + * @param workflowId the workflow id of the paused workflow + */ + public abstract void resumeWorkflow(String workflowId); + + /** + * Skips a given task from a current RUNNING workflow + * + * @param workflowId the id of the workflow instance + * @param taskReferenceName the reference name of the task to be skipped + */ + public abstract void skipTaskFromWorkflow(String workflowId, String taskReferenceName); + + /** + * Reruns the workflow from a specific task + * + * @param workflowId the id of the workflow + * @param rerunWorkflowRequest the request containing the task to rerun from + * @return the id of the workflow + */ + public abstract String rerunWorkflow(String workflowId, RerunWorkflowRequest rerunWorkflowRequest); + + /** + * Restart a completed workflow + * + * @param workflowId the workflow id of the workflow to be restarted + * @param useLatestDefinitions if true, use the latest workflow and task definitions when + * restarting the workflow if false, use the workflow and task definitions embedded in the + * workflow execution when restarting the workflow + */ + public abstract void restart(String workflowId, boolean useLatestDefinitions); + + /** + * Retries the last failed task in a workflow + * + * @param workflowId the workflow id of the workflow with the failed task + */ + public abstract void retryLastFailedTask(String workflowId); + + /** + * Resets the callback times of all IN PROGRESS tasks to 0 for the given workflow + * + * @param workflowId the id of the workflow + */ + public abstract void resetCallbacksForInProgressTasks(String workflowId); + + /** + * Terminates the execution of the given workflow instance + * + * @param workflowId the id of the workflow to be terminated + * @param reason the reason to be logged and displayed + */ + public abstract void terminateWorkflow(String workflowId, String reason); + + /** + * Search for workflows based on payload + * + * @param query the search query + * @return the {@link SearchResult} containing the {@link WorkflowSummary} that match the query + */ + public abstract SearchResult search(String query); + + /** + * Search for workflows based on payload + * + * @param query the search query + * @return the {@link SearchResult} containing the {@link Workflow} that match the query + */ + public abstract SearchResult searchV2(String query); + + /** + * Paginated search for workflows based on payload + * + * @param start start value of page + * @param size number of workflows to be returned + * @param sort sort order + * @param freeText additional free text query + * @param query the search query + * @return the {@link SearchResult} containing the {@link WorkflowSummary} that match the query + */ + public abstract SearchResult search( + Integer start, Integer size, String sort, String freeText, String query); + + /** + * Paginated search for workflows based on payload + * + * @param start start value of page + * @param size number of workflows to be returned + * @param sort sort order + * @param freeText additional free text query + * @param query the search query + * @return the {@link SearchResult} containing the {@link Workflow} that match the query + */ + public abstract SearchResult searchV2( + Integer start, Integer size, String sort, String freeText, String query); + public abstract Workflow testWorkflow(WorkflowTestRequest testRequest); +} diff --git a/src/main/java/com/netflix/conductor/client/telemetry/MetricsContainer.java b/src/main/java/com/netflix/conductor/client/telemetry/MetricsContainer.java new file mode 100644 index 00000000..21bc27e1 --- /dev/null +++ b/src/main/java/com/netflix/conductor/client/telemetry/MetricsContainer.java @@ -0,0 +1,183 @@ +/* + * Copyright 2020 Orkes, Inc. + *

+ * Licensed 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 com.netflix.conductor.client.telemetry; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import com.netflix.spectator.api.*; +import com.netflix.spectator.api.patterns.PolledMeter; + +public class MetricsContainer { + + private static final String TASK_TYPE = "taskType"; + private static final String WORKFLOW_TYPE = "workflowType"; + private static final String WORKFLOW_VERSION = "version"; + private static final String EXCEPTION = "exception"; + private static final String ENTITY_NAME = "entityName"; + private static final String OPERATION = "operation"; + private static final String PAYLOAD_TYPE = "payload_type"; + + private static final String TASK_EXECUTION_QUEUE_FULL = "task_execution_queue_full"; + private static final String TASK_POLL_ERROR = "task_poll_error"; + private static final String TASK_PAUSED = "task_paused"; + private static final String TASK_EXECUTE_ERROR = "task_execute_error"; + private static final String TASK_ACK_FAILED = "task_ack_failed"; + private static final String TASK_ACK_ERROR = "task_ack_error"; + private static final String TASK_UPDATE_ERROR = "task_update_error"; + private static final String TASK_POLL_COUNTER = "task_poll_counter"; + private static final String TASK_EXECUTE_TIME = "task_execute_time"; + private static final String TASK_POLL_TIME = "task_poll_time"; + private static final String TASK_RESULT_SIZE = "task_result_size"; + private static final String WORKFLOW_INPUT_SIZE = "workflow_input_size"; + private static final String EXTERNAL_PAYLOAD_USED = "external_payload_used"; + private static final String WORKFLOW_START_ERROR = "workflow_start_error"; + private static final String THREAD_UNCAUGHT_EXCEPTION = "thread_uncaught_exceptions"; + + private static final Registry REGISTRY = Spectator.globalRegistry(); + private static final Map TIMERS = new ConcurrentHashMap<>(); + private static final Map COUNTERS = new ConcurrentHashMap<>(); + private static final Map GAUGES = new ConcurrentHashMap<>(); + private static final String CLASS_NAME = MetricsContainer.class.getSimpleName(); + + private MetricsContainer() {} + + public static Timer getPollTimer(String taskType) { + return getTimer(TASK_POLL_TIME, TASK_TYPE, taskType); + } + + public static Timer getExecutionTimer(String taskType) { + return getTimer(TASK_EXECUTE_TIME, TASK_TYPE, taskType); + } + + private static Timer getTimer(String name, String... additionalTags) { + String key = CLASS_NAME + "." + name + "." + String.join(",", additionalTags); + return TIMERS.computeIfAbsent( + key, + k -> { + List tagList = getTags(additionalTags); + tagList.add(new BasicTag("unit", TimeUnit.MILLISECONDS.name())); + return REGISTRY.timer(name, tagList); + }); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private static List getTags(String[] additionalTags) { + List tagList = new ArrayList(); + tagList.add(new BasicTag("class", CLASS_NAME)); + for (int j = 0; j < additionalTags.length - 1; j++) { + tagList.add(new BasicTag(additionalTags[j], additionalTags[j + 1])); + j++; + } + return tagList; + } + + private static void incrementCount(String name, String... additionalTags) { + getCounter(name, additionalTags).increment(); + } + + private static Counter getCounter(String name, String... additionalTags) { + String key = CLASS_NAME + "." + name + "." + String.join(",", additionalTags); + return COUNTERS.computeIfAbsent( + key, + k -> { + List tags = getTags(additionalTags); + return REGISTRY.counter(name, tags); + }); + } + + private static AtomicLong getGauge(String name, String... additionalTags) { + String key = CLASS_NAME + "." + name + "." + String.join(",", additionalTags); + return GAUGES.computeIfAbsent( + key, + pollTimer -> { + Id id = REGISTRY.createId(name, getTags(additionalTags)); + return PolledMeter.using(REGISTRY).withId(id).monitorValue(new AtomicLong(0)); + }); + } + + public static void incrementTaskExecutionQueueFullCount(String taskType) { + incrementCount(TASK_EXECUTION_QUEUE_FULL, TASK_TYPE, taskType); + } + + public static void incrementUncaughtExceptionCount() { + incrementCount(THREAD_UNCAUGHT_EXCEPTION); + } + + public static void incrementTaskPollErrorCount(String taskType, Exception e) { + incrementCount( + TASK_POLL_ERROR, TASK_TYPE, taskType, EXCEPTION, e.getClass().getSimpleName()); + } + + public static void incrementTaskPausedCount(String taskType) { + incrementCount(TASK_PAUSED, TASK_TYPE, taskType); + } + + public static void incrementTaskExecutionErrorCount(String taskType, Throwable e) { + incrementCount( + TASK_EXECUTE_ERROR, TASK_TYPE, taskType, EXCEPTION, e.getClass().getSimpleName()); + } + + public static void incrementTaskAckFailedCount(String taskType) { + incrementCount(TASK_ACK_FAILED, TASK_TYPE, taskType); + } + + public static void incrementTaskAckErrorCount(String taskType, Exception e) { + incrementCount( + TASK_ACK_ERROR, TASK_TYPE, taskType, EXCEPTION, e.getClass().getSimpleName()); + } + + public static void recordTaskResultPayloadSize(String taskType, long payloadSize) { + getGauge(TASK_RESULT_SIZE, TASK_TYPE, taskType).getAndSet(payloadSize); + } + + public static void incrementTaskUpdateErrorCount(String taskType, Throwable t) { + incrementCount( + TASK_UPDATE_ERROR, TASK_TYPE, taskType, EXCEPTION, t.getClass().getSimpleName()); + } + + public static void incrementTaskPollCount(String taskType, int taskCount) { + getCounter(TASK_POLL_COUNTER, TASK_TYPE, taskType).increment(taskCount); + } + + public static void recordWorkflowInputPayloadSize( + String workflowType, String version, long payloadSize) { + getGauge(WORKFLOW_INPUT_SIZE, WORKFLOW_TYPE, workflowType, WORKFLOW_VERSION, version) + .getAndSet(payloadSize); + } + + public static void incrementExternalPayloadUsedCount( + String name, String operation, String payloadType) { + incrementCount( + EXTERNAL_PAYLOAD_USED, + ENTITY_NAME, + name, + OPERATION, + operation, + PAYLOAD_TYPE, + payloadType); + } + + public static void incrementWorkflowStartErrorCount(String workflowType, Throwable t) { + incrementCount( + WORKFLOW_START_ERROR, + WORKFLOW_TYPE, + workflowType, + EXCEPTION, + t.getClass().getSimpleName()); + } +} diff --git a/src/main/java/com/netflix/conductor/client/worker/Worker.java b/src/main/java/com/netflix/conductor/client/worker/Worker.java new file mode 100644 index 00000000..72207087 --- /dev/null +++ b/src/main/java/com/netflix/conductor/client/worker/Worker.java @@ -0,0 +1,118 @@ +/* + * Copyright 2021 Orkes, Inc. + *

+ * Licensed 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 com.netflix.conductor.client.worker; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.function.Function; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.netflix.conductor.client.config.PropertyFactory; +import com.netflix.conductor.common.metadata.tasks.Task; +import com.netflix.conductor.common.metadata.tasks.TaskResult; + +import com.amazonaws.util.EC2MetadataUtils; + +public interface Worker { + + /** + * Retrieve the name of the task definition the worker is currently working on. + * + * @return the name of the task definition. + */ + String getTaskDefName(); + + /** + * Executes a task and returns the updated task. + * + * @param task Task to be executed. + * @return the {@link TaskResult} object If the task is not completed yet, return with the + * status as IN_PROGRESS. + */ + TaskResult execute(Task task); + + /** + * Called when the task coordinator fails to update the task to the server. Client should store + * the task id (in a database) and retry the update later + * + * @param task Task which cannot be updated back to the server. + */ + default void onErrorUpdate(Task task) {} + + /** + * Override this method to pause the worker from polling. + * + * @return true if the worker is paused and no more tasks should be polled from server. + */ + default boolean paused() { + return PropertyFactory.getBoolean(getTaskDefName(), "paused", false); + } + + /** + * Override this method to app specific rules. + * + * @return returns the serverId as the id of the instance that the worker is running. + */ + default String getIdentity() { + String serverId; + try { + serverId = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + serverId = System.getenv("HOSTNAME"); + } + if (serverId == null) { + serverId = + (EC2MetadataUtils.getInstanceId() == null) + ? System.getProperty("user.name") + : EC2MetadataUtils.getInstanceId(); + } + LoggerHolder.logger.debug("Setting worker id to {}", serverId); + return serverId; + } + + /** + * Override this method to change the interval between polls. + * + * @return interval in millisecond at which the server should be polled for worker tasks. + */ + default int getPollingInterval() { + return PropertyFactory.getInteger(getTaskDefName(), "pollInterval", 1000); + } + + static Worker create(String taskType, Function executor) { + return new Worker() { + + @Override + public String getTaskDefName() { + return taskType; + } + + @Override + public TaskResult execute(Task task) { + return executor.apply(task); + } + + @Override + public boolean paused() { + return Worker.super.paused(); + } + }; + } +} + +final class LoggerHolder { + + static final Logger logger = LoggerFactory.getLogger(Worker.class); +} diff --git a/src/main/java/io/orkes/conductor/client/ApiClient.java b/src/main/java/io/orkes/conductor/client/ApiClient.java index ad7e55ec..23a0976f 100644 --- a/src/main/java/io/orkes/conductor/client/ApiClient.java +++ b/src/main/java/io/orkes/conductor/client/ApiClient.java @@ -33,6 +33,8 @@ import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -63,15 +65,13 @@ public class ApiClient { private static final Logger LOGGER = LoggerFactory.getLogger(ApiClient.class); private static final String TOKEN_CACHE_KEY = "TOKEN"; - private final Cache tokenCache; + private Cache tokenCache; private final String basePath; private final Map defaultHeaderMap = new HashMap(); private String tempFolderPath; - private Map authentications; - private InputStream sslCaCert; private boolean verifyingSsl; private KeyManager[] keyManagers; @@ -91,51 +91,67 @@ public class ApiClient { private int executorThreadCount = 0; + private long tokenRefreshInSeconds = 2700; //45 minutes + + private ScheduledExecutorService tokenRefreshService; /* * Constructor for ApiClient */ public ApiClient() { - this("http://localhost:8080/api"); + this("http://localhost:8080/api", null, null); } public ApiClient(String basePath) { - this.tokenCache = CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).build(); - if(basePath.endsWith("/")) { - basePath = basePath.substring(0, basePath.length()-1); - } - this.basePath = basePath; - httpClient = new OkHttpClient(); - httpClient.setRetryOnConnectionFailure(true); - verifyingSsl = true; - json = new JSON(); - authentications = new HashMap<>(); + this(basePath, null, null); } public ApiClient(String basePath, SecretsManager secretsManager, String keyPath, String secretPath) { - this(basePath); - try { - keyId = secretsManager.getSecret(keyPath); - keySecret = secretsManager.getSecret(secretPath); - getToken(); - } catch (Throwable t) { - LOGGER.error(t.getMessage(), t); - } + this(basePath, secretsManager.getSecret(keyPath), secretsManager.getSecret(secretPath)); } public ApiClient(String basePath, String keyId, String keySecret) { - this(basePath); + if(basePath.endsWith("/")) { + basePath = basePath.substring(0, basePath.length()-1); + } + this.basePath = basePath; + this.keyId = keyId; this.keySecret = keySecret; - try { - getToken(); - } catch (Throwable t) { - LOGGER.error(t.getMessage(), t); + this.httpClient = new OkHttpClient(); + this.httpClient.setRetryOnConnectionFailure(true); + this.verifyingSsl = true; + this.json = new JSON(); + String refreshInterval = System.getenv("CONDUCTOR_SECURITY_TOKEN_REFRESH_INTERVAL"); + if(refreshInterval == null) { + refreshInterval = System.getProperty("CONDUCTOR_SECURITY_TOKEN_REFRESH_INTERVAL"); + } + if(refreshInterval != null) { + try { + this.tokenRefreshInSeconds = Integer.parseInt(refreshInterval); + }catch (Exception ignored){} + } + LOGGER.info("Setting token refresh interval to {} seconds", this.tokenRefreshInSeconds); + this.tokenCache = CacheBuilder.newBuilder().expireAfterWrite(tokenRefreshInSeconds, TimeUnit.SECONDS).build(); + if(useSecurity()) { + scheduleTokenRefresh(); + try { + //This should be in the try catch so if the client is initialized and if the server is down or not reachable + //Client will still initialize without errors + getToken(); + } catch (Throwable t) { + LOGGER.error(t.getMessage(), t); + } } } - public ApiClient(String basePath, String token) { - this(basePath); + private void scheduleTokenRefresh() { + this.tokenRefreshService = Executors.newSingleThreadScheduledExecutor(); + long refreshInterval = Math.max(30, tokenRefreshInSeconds - 30); + LOGGER.info("Starting token refresh thread to run at every {} seconds", refreshInterval); + this.tokenRefreshService.scheduleAtFixedRate(()-> { + refreshToken(); + }, refreshInterval,refreshInterval, TimeUnit.SECONDS); } public boolean useSecurity() { @@ -308,22 +324,22 @@ public ApiClient setKeyManagers(KeyManager[] managers) { } public ApiClient setDateFormat(DateFormat dateFormat) { - this.json.setDateFormat(dateFormat); + LOGGER.warn("This feature is deprecated"); return this; } public ApiClient setSqlDateFormat(DateFormat dateFormat) { - this.json.setSqlDateFormat(dateFormat); + LOGGER.warn("This feature is deprecated"); return this; } public ApiClient setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { - this.json.setOffsetDateTimeFormat(dateFormat); + LOGGER.warn("This feature is deprecated"); return this; } public ApiClient setLocalDateFormat(DateTimeFormatter dateFormat) { - this.json.setLocalDateFormat(dateFormat); + LOGGER.warn("This feature is deprecated"); return this; } @@ -338,13 +354,7 @@ public ApiClient setLenientOnJson(boolean lenientOnJson) { * @param apiKey API key */ public void setApiKey(String apiKey) { - for (Authentication auth : authentications.values()) { - if (auth instanceof ApiKeyAuth) { - ((ApiKeyAuth) auth).setApiKey(apiKey); - return; - } - } - throw new RuntimeException("No API key authentication configured!"); + this.keyId = apiKey; } /** @@ -1096,15 +1106,10 @@ public void processHeaderParams(Map headerParams, Request.Builde * @param headerParams Map of header parameters */ public void updateParamsForAuth(String[] authNames, List queryParams, Map headerParams) { - if(useSecurity() && authentications.isEmpty()) { - LOGGER.debug("No authentication set, will refresh token"); - refreshToken(); - } - for (String authName : authNames) { - Authentication auth = authentications.get(authName); - if (auth != null) { - auth.applyToParams(queryParams, headerParams); - } + String token = getToken(); + if(useSecurity()) { + Authentication auth = getApiKeyHeader(token); + auth.applyToParams(queryParams, headerParams); } } @@ -1259,19 +1264,19 @@ public String getToken() { } private String refreshToken() { + LOGGER.debug("Refreshing token @ {}", new Date()); if (this.keyId == null || this.keySecret == null) { throw new RuntimeException("KeyId and KeySecret must be set in order to get an authentication token"); } GenerateTokenRequest generateTokenRequest = new GenerateTokenRequest().keyId(this.keyId).keySecret(this.keySecret); Map response = TokenResourceApi.generateTokenWithHttpInfo(this, generateTokenRequest).getData(); String token = response.get("token"); - this.setApiKeyHeader(token); return token; } - private synchronized void setApiKeyHeader(String token) { + private ApiKeyAuth getApiKeyHeader(String token) { ApiKeyAuth apiKeyAuth = new ApiKeyAuth("header", "X-Authorization"); apiKeyAuth.setApiKey(token); - authentications.put("api_key", apiKeyAuth); + return apiKeyAuth; } } diff --git a/src/main/java/io/orkes/conductor/client/WorkflowClient.java b/src/main/java/io/orkes/conductor/client/WorkflowClient.java index 8a5c67c7..a092e81e 100644 --- a/src/main/java/io/orkes/conductor/client/WorkflowClient.java +++ b/src/main/java/io/orkes/conductor/client/WorkflowClient.java @@ -15,7 +15,6 @@ import java.time.Duration; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -23,10 +22,10 @@ import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest; import com.netflix.conductor.common.model.BulkResponse; import com.netflix.conductor.common.run.Workflow; +import com.netflix.conductor.common.run.WorkflowTestRequest; import io.orkes.conductor.client.http.ApiException; import io.orkes.conductor.client.model.WorkflowStatus; -import io.orkes.conductor.client.model.WorkflowTestRequest; import io.orkes.conductor.common.model.WorkflowRun; public abstract class WorkflowClient extends com.netflix.conductor.client.http.WorkflowClient { diff --git a/src/main/java/io/orkes/conductor/client/automator/TaskRunner.java b/src/main/java/io/orkes/conductor/client/automator/TaskRunner.java index a5473f26..c4d7588f 100644 --- a/src/main/java/io/orkes/conductor/client/automator/TaskRunner.java +++ b/src/main/java/io/orkes/conductor/client/automator/TaskRunner.java @@ -44,14 +44,12 @@ class TaskRunner { private static final Logger LOGGER = LoggerFactory.getLogger(TaskRunner.class); private static final Registry REGISTRY = Spectator.globalRegistry(); - private final EurekaClient eurekaClient; private final TaskClient taskClient; private final int updateRetryCount; private final ThreadPoolExecutor executorService; private final Map taskToDomain; private final int taskPollTimeout; - public static final String DOMAIN = "domain"; private static final String OVERRIDE_DISCOVERY = "pollOutOfDiscovery"; public static final String ALL_WORKERS = "all"; @@ -60,6 +58,16 @@ class TaskRunner { private final Worker worker; + private int pollingIntervalInMillis; + + private final String domain; + + private final String taskType; + + private int errorAt; + + private int pollingErrorCount = 0; + TaskRunner( Worker worker, EurekaClient eurekaClient, @@ -76,6 +84,22 @@ class TaskRunner { this.taskToDomain = taskToDomain; this.taskPollTimeout = taskPollTimeout; this.permits = new Semaphore(threadCount); + this.pollingIntervalInMillis = worker.getPollingInterval(); + this.taskType = worker.getTaskDefName(); + this.domain = Optional.ofNullable(PropertyFactory.getString(taskType, DOMAIN, null)) + .orElseGet(() -> Optional.ofNullable(PropertyFactory.getString(ALL_WORKERS, DOMAIN, null)) + .orElse(taskToDomain.get(taskType))); + + int defaultLoggingInterval = 100; + int errorInterval = PropertyFactory.getInteger(taskType, "LOG_INTERVAL", 0); + if(errorInterval == 0) { + errorInterval = PropertyFactory.getInteger(ALL_WORKERS, "LOG_INTERVAL", 0); + } + if(errorInterval == 0) { + errorInterval = defaultLoggingInterval; + } + this.errorAt = errorInterval; + LOGGER.info("Polling errors will be sampled at every {} error (after the first 100 errors) for taskType {}", this.errorAt, taskType); this.executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool( @@ -86,10 +110,13 @@ class TaskRunner { .build()); ThreadPoolMonitor.attach(REGISTRY, (ThreadPoolExecutor) executorService, workerNamePrefix); LOGGER.info( - "Initialized the TaskPollExecutor for {} with {} threads and threadPrefix {}", - worker.getTaskDefName(), + "Starting Worker for taskType '{}' with {} threads, {} polling interval (ms) and domain {}", + taskType, threadCount, - workerNamePrefix); + pollingIntervalInMillis, + domain); + LOGGER.info("Polling errors for taskType {} will be printed at every {} occurance.", taskType, errorAt); + } public void pollAndExecute() { @@ -101,12 +128,12 @@ public void pollAndExecute() { if (stopwatch == null) { stopwatch = Stopwatch.createStarted(); } - Uninterruptibles.sleepUninterruptibly(worker.getPollingInterval(), TimeUnit.MILLISECONDS); + Uninterruptibles.sleepUninterruptibly(pollingIntervalInMillis, TimeUnit.MILLISECONDS); continue; } if (stopwatch != null) { stopwatch.stop(); - LOGGER.trace("Poller for task {} waited for {} ms before getting {} tasks to execute", worker.getTaskDefName(), stopwatch.elapsed(TimeUnit.MILLISECONDS), tasks.size()); + LOGGER.trace("Poller for task {} waited for {} ms before getting {} tasks to execute", taskType, stopwatch.elapsed(TimeUnit.MILLISECONDS), tasks.size()); stopwatch = null; } tasks.forEach(task -> this.executorService.submit(() -> this.processTask(task))); @@ -138,7 +165,7 @@ private List pollTasksForWorker() { Boolean discoveryOverride = Optional.ofNullable( PropertyFactory.getBoolean( - worker.getTaskDefName(), OVERRIDE_DISCOVERY, null)) + taskType, OVERRIDE_DISCOVERY, null)) .orElseGet( () -> PropertyFactory.getBoolean( @@ -150,11 +177,10 @@ private List pollTasksForWorker() { return tasks; } if (worker.paused()) { - MetricsContainer.incrementTaskPausedCount(worker.getTaskDefName()); + MetricsContainer.incrementTaskPausedCount(taskType); LOGGER.trace("Worker {} has been paused. Not polling anymore!", worker.getClass()); return tasks; } - String taskType = worker.getTaskDefName(); int pollCount = 0; while(permits.tryAcquire()){ pollCount++; @@ -165,7 +191,7 @@ private List pollTasksForWorker() { try { - String domain = Optional.ofNullable(PropertyFactory.getString(taskType, DOMAIN, null)).orElseGet(() -> Optional.ofNullable(PropertyFactory.getString(ALL_WORKERS, DOMAIN, null)).orElse(taskToDomain.get(taskType))); + LOGGER.trace("Polling task of type: {} in domain: '{}' with size {}", taskType, domain, pollCount); Stopwatch stopwatch = Stopwatch.createStarted(); int tasksToPoll = pollCount; @@ -175,8 +201,21 @@ private List pollTasksForWorker() { LOGGER.debug("Time taken to poll {} task with a batch size of {} is {} ms", taskType, tasks.size(), stopwatch.elapsed(TimeUnit.MILLISECONDS)); } catch (Throwable e) { - LOGGER.error("Error when polling for tasks: {}", e.getMessage(), e); permits.release(pollCount - tasks.size()); + + //For the first 100 errors, just print them as is... + boolean printError = false; + if(pollingErrorCount < 100 || pollingErrorCount % errorAt == 0) { + printError = true; + } + pollingErrorCount++; + if(pollingErrorCount > 10_000_000) { + //Reset after 10 million errors + pollingErrorCount = 0; + } + if(printError) { + LOGGER.error("Error polling for taskType: {}, error = {}", taskType, e.getMessage(), e); + } } return tasks; } @@ -185,7 +224,6 @@ private List pollTask(String domain, int count) { if (count < 1) { return Collections.emptyList(); } - String taskType = worker.getTaskDefName(); String workerId = worker.getIdentity(); LOGGER.debug("poll {} in the domain {} with batch size {}", taskType, domain, count); return taskClient.batchPollTasksInDomain( @@ -201,7 +239,7 @@ private List pollTask(String domain, int count) { }; private void processTask(Task task) { - LOGGER.trace("Executing task: {} of type: {} in worker: {} at {}", task.getTaskId(), task.getTaskDefName(), worker.getClass().getSimpleName(), worker.getIdentity()); + LOGGER.trace("Executing task: {} of type: {} in worker: {} at {}", task.getTaskId(), taskType, worker.getClass().getSimpleName(), worker.getIdentity()); LOGGER.trace("task {} is getting executed after {} ms of getting polled", task.getTaskId(), (System.currentTimeMillis()-task.getStartTime())); try { Stopwatch stopwatch = Stopwatch.createStarted(); @@ -324,7 +362,7 @@ private R retryOperation(Function operation, int count, T input, St private void handleException(Throwable t, TaskResult result, Worker worker, Task task) { LOGGER.error(String.format("Error while executing task %s", task.toString()), t); - MetricsContainer.incrementTaskExecutionErrorCount(worker.getTaskDefName(), t); + MetricsContainer.incrementTaskExecutionErrorCount(taskType, t); result.setStatus(TaskResult.Status.FAILED); result.setReasonForIncompletion("Error while executing the task: " + t); StringWriter stringWriter = new StringWriter(); diff --git a/src/main/java/io/orkes/conductor/client/automator/TaskRunnerConfigurer.java b/src/main/java/io/orkes/conductor/client/automator/TaskRunnerConfigurer.java index 97be31c3..cb58094f 100644 --- a/src/main/java/io/orkes/conductor/client/automator/TaskRunnerConfigurer.java +++ b/src/main/java/io/orkes/conductor/client/automator/TaskRunnerConfigurer.java @@ -296,7 +296,6 @@ private void startWorker(Worker worker) { this.taskToThreadCount.getOrDefault(worker.getTaskDefName(), threadCount); final Integer taskPollTimeout = this.taskPollTimeout.getOrDefault(worker.getTaskDefName(), defaultPollTimeout); - LOGGER.info("Starting worker: {} with {} threads and {} pollTimeout", worker.getTaskDefName(),threadCountForTask, taskPollTimeout); LOGGER.info("Domain map for tasks = {}", taskToDomain); final TaskRunner taskRunner = new TaskRunner( @@ -316,7 +315,6 @@ private void startPooledGRPCWorker(Worker worker) { final Integer threadCountForTask = this.taskToThreadCount.getOrDefault(worker.getTaskDefName(), threadCount); final Integer taskPollTimeout = this.taskPollTimeout.getOrDefault(worker.getTaskDefName(), defaultPollTimeout); - final Integer taskPollcount = this.taskPollCount.getOrDefault(worker.getTaskDefName(), defaultPollCount); String taskType = worker.getTaskDefName(); String domain = Optional.ofNullable(PropertyFactory.getString(taskType, DOMAIN, null)) @@ -324,7 +322,7 @@ private void startPooledGRPCWorker(Worker worker) { LOGGER.info("Starting gRPC worker: {} with {} threads", worker.getTaskDefName(), threadCountForTask); ThreadPoolExecutor executor = new ThreadPoolExecutor(threadCountForTask, threadCountForTask, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(threadCountForTask * 100)); - PooledPoller pooledPoller = new PooledPoller(apiClient, worker, domain, taskPollcount, taskPollTimeout, executor, threadCountForTask); + PooledPoller pooledPoller = new PooledPoller(apiClient, worker, domain, threadCountForTask, taskPollTimeout, executor, threadCountForTask); pooledPoller.start(); } } diff --git a/src/main/java/io/orkes/conductor/client/http/JSON.java b/src/main/java/io/orkes/conductor/client/http/JSON.java index b4e2b59d..c16e0787 100644 --- a/src/main/java/io/orkes/conductor/client/http/JSON.java +++ b/src/main/java/io/orkes/conductor/client/http/JSON.java @@ -12,50 +12,21 @@ */ package io.orkes.conductor.client.http; -import java.io.IOException; -import java.io.StringReader; import java.lang.reflect.Type; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.ParsePosition; -import java.util.Date; -import org.threeten.bp.LocalDate; -import org.threeten.bp.OffsetDateTime; -import org.threeten.bp.format.DateTimeFormatter; +import com.netflix.conductor.common.config.ObjectMapperProvider; -import com.google.gson.*; -import com.google.gson.internal.bind.util.ISO8601Utils; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; -import io.gsonfire.GsonFireBuilder; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.SneakyThrows; public class JSON { - private final Gson gson; - private boolean isLenientOnJson = false; - private DateTypeAdapter dateTypeAdapter = new DateTypeAdapter(); - private SqlDateTypeAdapter sqlDateTypeAdapter = new SqlDateTypeAdapter(); - private OffsetDateTimeTypeAdapter offsetDateTimeTypeAdapter = new OffsetDateTimeTypeAdapter(); - private LocalDateTypeAdapter localDateTypeAdapter = new LocalDateTypeAdapter(); - - public static GsonBuilder createGson() { - GsonFireBuilder fireBuilder = new GsonFireBuilder(); - return fireBuilder.createGsonBuilder(); - } - + private final ObjectMapper objectMapper; public JSON() { - gson = createGson() - .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) - .registerTypeAdapter(Date.class, dateTypeAdapter) - .registerTypeAdapter(java.sql.Date.class, sqlDateTypeAdapter) - .registerTypeAdapter(OffsetDateTime.class, offsetDateTimeTypeAdapter) - .registerTypeAdapter(LocalDate.class, localDateTypeAdapter) - .serializeNulls() - .create(); + objectMapper = new ObjectMapperProvider().getObjectMapper(); } public JSON setLenientOnJson(boolean lenientOnJson) { - isLenientOnJson = lenientOnJson; return this; } @@ -65,8 +36,9 @@ public JSON setLenientOnJson(boolean lenientOnJson) { * @param obj Object * @return String representation of the JSON */ + @SneakyThrows public String serialize(Object obj) { - return gson.toJson(obj); + return objectMapper.writeValueAsString(obj); } /** @@ -80,232 +52,15 @@ public String serialize(Object obj) { @SuppressWarnings("unchecked") public T deserialize(String body, Type returnType) { try { - if (isLenientOnJson) { - JsonReader jsonReader = new JsonReader(new StringReader(body)); - // see - // https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean) - jsonReader.setLenient(true); - return gson.fromJson(jsonReader, returnType); - } else { - return gson.fromJson(body, returnType); - } - } catch (JsonParseException e) { - // Fallback processing when failed to parse JSON form response body: - // return the response body string directly for the String return type; - if (returnType.equals(String.class)) return (T) body; - else throw (e); - } - } - - /** Gson TypeAdapter for JSR310 OffsetDateTime type */ - public static class OffsetDateTimeTypeAdapter extends TypeAdapter { - - private DateTimeFormatter formatter; - - public OffsetDateTimeTypeAdapter() { - this(DateTimeFormatter.ISO_OFFSET_DATE_TIME); - } - - public OffsetDateTimeTypeAdapter(DateTimeFormatter formatter) { - this.formatter = formatter; - } - - public void setFormat(DateTimeFormatter dateFormat) { - this.formatter = dateFormat; - } - - @Override - public void write(JsonWriter out, OffsetDateTime date) throws IOException { - if (date == null) { - out.nullValue(); - } else { - out.value(formatter.format(date)); - } - } - - @Override - public OffsetDateTime read(JsonReader in) throws IOException { - switch (in.peek()) { - case NULL: - in.nextNull(); - return null; - default: - String date = in.nextString(); - if (date.endsWith("+0000")) { - date = date.substring(0, date.length() - 5) + "Z"; - } - return OffsetDateTime.parse(date, formatter); - } - } - } - - /** Gson TypeAdapter for JSR310 LocalDate type */ - public class LocalDateTypeAdapter extends TypeAdapter { - - private DateTimeFormatter formatter; - - public LocalDateTypeAdapter() { - this(DateTimeFormatter.ISO_LOCAL_DATE); - } - - public LocalDateTypeAdapter(DateTimeFormatter formatter) { - this.formatter = formatter; - } - - public void setFormat(DateTimeFormatter dateFormat) { - this.formatter = dateFormat; - } - - @Override - public void write(JsonWriter out, LocalDate date) throws IOException { - if (date == null) { - out.nullValue(); - } else { - out.value(formatter.format(date)); + if (returnType.equals(String.class)) { + return (T) body; } - } - @Override - public LocalDate read(JsonReader in) throws IOException { - switch (in.peek()) { - case NULL: - in.nextNull(); - return null; - default: - String date = in.nextString(); - return LocalDate.parse(date, formatter); - } + JavaType javaType = objectMapper.getTypeFactory().constructType(returnType); + return objectMapper.readValue(body, javaType); + } catch (Exception e) { + throw new RuntimeException(e); } } - public JSON setOffsetDateTimeFormat(DateTimeFormatter dateFormat) { - offsetDateTimeTypeAdapter.setFormat(dateFormat); - return this; - } - - public JSON setLocalDateFormat(DateTimeFormatter dateFormat) { - localDateTypeAdapter.setFormat(dateFormat); - return this; - } - - /** - * Gson TypeAdapter for java.sql.Date type If the dateFormat is null, a simple "yyyy-MM-dd" - * format will be used (more efficient than SimpleDateFormat). - */ - public static class SqlDateTypeAdapter extends TypeAdapter { - - private DateFormat dateFormat; - - public SqlDateTypeAdapter() {} - - public SqlDateTypeAdapter(DateFormat dateFormat) { - this.dateFormat = dateFormat; - } - - public void setFormat(DateFormat dateFormat) { - this.dateFormat = dateFormat; - } - - @Override - public void write(JsonWriter out, java.sql.Date date) throws IOException { - if (date == null) { - out.nullValue(); - } else { - String value; - if (dateFormat != null) { - value = dateFormat.format(date); - } else { - value = date.toString(); - } - out.value(value); - } - } - - @Override - public java.sql.Date read(JsonReader in) throws IOException { - switch (in.peek()) { - case NULL: - in.nextNull(); - return null; - default: - String date = in.nextString(); - try { - if (dateFormat != null) { - return new java.sql.Date(dateFormat.parse(date).getTime()); - } - return new java.sql.Date( - ISO8601Utils.parse(date, new ParsePosition(0)).getTime()); - } catch (ParseException e) { - throw new JsonParseException(e); - } - } - } - } - - /** - * Gson TypeAdapter for java.util.Date type If the dateFormat is null, ISO8601Utils will be - * used. - */ - public static class DateTypeAdapter extends TypeAdapter { - - private DateFormat dateFormat; - - public DateTypeAdapter() {} - - public DateTypeAdapter(DateFormat dateFormat) { - this.dateFormat = dateFormat; - } - - public void setFormat(DateFormat dateFormat) { - this.dateFormat = dateFormat; - } - - @Override - public void write(JsonWriter out, Date date) throws IOException { - if (date == null) { - out.nullValue(); - } else { - String value; - if (dateFormat != null) { - value = dateFormat.format(date); - } else { - value = ISO8601Utils.format(date, true); - } - out.value(value); - } - } - - @Override - public Date read(JsonReader in) throws IOException { - try { - switch (in.peek()) { - case NULL: - in.nextNull(); - return null; - default: - String date = in.nextString(); - try { - if (dateFormat != null) { - return dateFormat.parse(date); - } - return ISO8601Utils.parse(date, new ParsePosition(0)); - } catch (ParseException e) { - throw new JsonParseException(e); - } - } - } catch (IllegalArgumentException e) { - throw new JsonParseException(e); - } - } - } - - public JSON setDateFormat(DateFormat dateFormat) { - dateTypeAdapter.setFormat(dateFormat); - return this; - } - - public JSON setSqlDateFormat(DateFormat dateFormat) { - sqlDateTypeAdapter.setFormat(dateFormat); - return this; - } } diff --git a/src/main/java/io/orkes/conductor/client/http/OrkesMetadataClient.java b/src/main/java/io/orkes/conductor/client/http/OrkesMetadataClient.java index 836b47d8..b7ed522e 100644 --- a/src/main/java/io/orkes/conductor/client/http/OrkesMetadataClient.java +++ b/src/main/java/io/orkes/conductor/client/http/OrkesMetadataClient.java @@ -90,6 +90,11 @@ public void unregisterWorkflowDef(String name, Integer version) { metadataResourceApi.unregisterWorkflowDef(name, version); } + @Override + public List getAllTaskDefs() { + return metadataResourceApi.getTaskDefs(null, false, null, null); + } + @Override public void registerTaskDefs(List taskDefs) { metadataResourceApi.registerTaskDef(taskDefs); diff --git a/src/main/java/io/orkes/conductor/client/http/OrkesTaskClient.java b/src/main/java/io/orkes/conductor/client/http/OrkesTaskClient.java index 68eeb169..6cbbbeb6 100644 --- a/src/main/java/io/orkes/conductor/client/http/OrkesTaskClient.java +++ b/src/main/java/io/orkes/conductor/client/http/OrkesTaskClient.java @@ -33,7 +33,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; -public class OrkesTaskClient extends TaskClient implements AutoCloseable{ +public class OrkesTaskClient extends TaskClient implements AutoCloseable { protected ApiClient apiClient; @@ -61,6 +61,11 @@ public OrkesTaskClient setWriteTimeout(int writeTimeout) { return this; } + public OrkesTaskClient withWriteTimeout(int writeTimeout) { + apiClient.setWriteTimeout(writeTimeout); + return this; + } + public OrkesTaskClient withConnectTimeout(int connectTimeout) { apiClient.setConnectTimeout(connectTimeout); return this; @@ -70,6 +75,15 @@ public ApiClient getApiClient() { return apiClient; } + /** + * + * @return ObjectMapper used to serialize objects - can be modified to add additional modules. + */ + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + @Override public Task pollTask(String taskType, String workerId, String domain) { List tasks = batchPollTasksInDomain(taskType, domain, workerId, 1, 100); diff --git a/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java b/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java index 65807e14..a509806f 100644 --- a/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java +++ b/src/main/java/io/orkes/conductor/client/http/OrkesWorkflowClient.java @@ -16,7 +16,6 @@ import java.time.temporal.ChronoUnit; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.UUID; import java.util.concurrent.*; @@ -29,6 +28,7 @@ import com.netflix.conductor.common.run.SearchResult; import com.netflix.conductor.common.run.Workflow; import com.netflix.conductor.common.run.WorkflowSummary; +import com.netflix.conductor.common.run.WorkflowTestRequest; import io.orkes.conductor.client.ApiClient; import io.orkes.conductor.client.WorkflowClient; @@ -37,12 +37,11 @@ import io.orkes.conductor.client.http.api.WorkflowResourceApi; import io.orkes.conductor.client.model.CorrelationIdsSearchRequest; import io.orkes.conductor.client.model.WorkflowStatus; -import io.orkes.conductor.client.model.WorkflowTestRequest; import io.orkes.conductor.common.model.WorkflowRun; import com.google.common.base.Preconditions; -public class OrkesWorkflowClient extends WorkflowClient { +public class OrkesWorkflowClient extends WorkflowClient implements AutoCloseable { protected ApiClient apiClient; @@ -335,10 +334,17 @@ public Workflow updateVariables(String workflowId, Map variables @Override public void shutdown() { if(apiClient.isUseGRPC()) { - grpcWorkflowClient.shutdown(); + if(grpcWorkflowClient != null) { + grpcWorkflowClient.shutdown(); + } } if(executorService != null) { - executorService.shutdown();; + executorService.shutdown(); } } + + @Override + public void close() { + shutdown(); + } } diff --git a/src/main/java/io/orkes/conductor/client/http/api/ApplicationResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/ApplicationResourceApi.java index 2214523d..920e4e28 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/ApplicationResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/ApplicationResourceApi.java @@ -23,7 +23,7 @@ import io.orkes.conductor.client.http.*; import io.orkes.conductor.client.model.*; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; public class ApplicationResourceApi { private ApiClient apiClient; @@ -167,7 +167,7 @@ private ApiResponse addRoleToApplicationUserWithHttpInfo( String applicationId, String role) throws ApiException { com.squareup.okhttp.Call call = addRoleToApplicationUserValidateBeforeCall(applicationId, role, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -283,7 +283,7 @@ public CreateAccessKeyResponse createAccessKey(String id) throws ApiException { private ApiResponse createAccessKeyWithHttpInfo(String id) throws ApiException { com.squareup.okhttp.Call call = createAccessKeyValidateBeforeCall(id, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -399,7 +399,7 @@ public ConductorApplication createApplication(CreateOrUpdateApplicationRequest c */ private ApiResponse createApplicationWithHttpInfo(CreateOrUpdateApplicationRequest createOrUpdateApplicationRequest) throws ApiException { com.squareup.okhttp.Call call = createApplicationValidateBeforeCall(createOrUpdateApplicationRequest, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -530,7 +530,7 @@ private ApiResponse deleteAccessKeyWithHttpInfo(String applicationId, St throws ApiException { com.squareup.okhttp.Call call = deleteAccessKeyValidateBeforeCall(applicationId, keyId, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -644,7 +644,7 @@ public void deleteApplication(String id) throws ApiException { */ private ApiResponse deleteApplicationWithHttpInfo(String id) throws ApiException { com.squareup.okhttp.Call call = deleteApplicationValidateBeforeCall(id, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -761,7 +761,7 @@ public List getAccessKeys(String id) throws ApiException { private ApiResponse> getAccessKeysWithHttpInfo(String id) throws ApiException { com.squareup.okhttp.Call call = getAccessKeysValidateBeforeCall(id, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -878,7 +878,7 @@ public ConductorApplication getApplication(String id) throws ApiException { private ApiResponse getApplicationWithHttpInfo(String id) throws ApiException { com.squareup.okhttp.Call call = getApplicationValidateBeforeCall(id, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -983,7 +983,7 @@ public List listApplications() throws ApiException { private ApiResponse> listApplicationsWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = listApplicationsValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1111,7 +1111,7 @@ private ApiResponse removeRoleFromApplicationUserWithHttpInfo( String applicationId, String role) throws ApiException { com.squareup.okhttp.Call call = removeRoleFromApplicationUserValidateBeforeCall(applicationId, role, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1246,7 +1246,7 @@ private ApiResponse toggleAccessKeyStatusWithHttpInfo( String applicationId, String keyId) throws ApiException { com.squareup.okhttp.Call call = toggleAccessKeyStatusValidateBeforeCall(applicationId, keyId, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1382,7 +1382,7 @@ private ApiResponse updateApplicationWithHttpInfo( com.squareup.okhttp.Call call = updateApplicationValidateBeforeCall( createOrUpdateApplicationRequest, id, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } } diff --git a/src/main/java/io/orkes/conductor/client/http/api/AuthorizationResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/AuthorizationResourceApi.java index 616f8bae..a2126172 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/AuthorizationResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/AuthorizationResourceApi.java @@ -24,7 +24,7 @@ import io.orkes.conductor.client.model.AuthorizationRequest; import io.orkes.conductor.client.model.Subject; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; public class AuthorizationResourceApi { private ApiClient apiClient; @@ -169,7 +169,7 @@ public Map> getPermissions(String type, String id) throws private ApiResponse>> getPermissionsWithHttpInfo( String type, String id) throws ApiException { com.squareup.okhttp.Call call = getPermissionsValidateBeforeCall(type, id, null, null); - Type localVarReturnType = new TypeToken>>() {}.getType(); + Type localVarReturnType = new TypeReference>>() {}.getType(); return apiClient.execute(call, localVarReturnType); } diff --git a/src/main/java/io/orkes/conductor/client/http/api/EventResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/EventResourceApi.java index 3e82c28d..ea4cbf3e 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/EventResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/EventResourceApi.java @@ -24,7 +24,7 @@ import io.orkes.conductor.client.ApiClient; import io.orkes.conductor.client.http.*; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; public class EventResourceApi { private ApiClient apiClient; @@ -287,7 +287,7 @@ private ApiResponse deleteQueueConfigWithHttpInfo(String queueType, Stri throws ApiException { com.squareup.okhttp.Call call = deleteQueueConfigValidateBeforeCall(queueType, queueName, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -391,7 +391,7 @@ public List getEventHandlers() throws ApiException { */ private ApiResponse> getEventHandlersWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = getEventHandlersValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -520,7 +520,7 @@ private ApiResponse> getEventHandlersForEventWithHttpInfo( String event, Boolean activeOnly) throws ApiException { com.squareup.okhttp.Call call = getEventHandlersForEventValidateBeforeCall(event, activeOnly, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -653,7 +653,7 @@ private ApiResponse getQueueConfigWithHttpInfo(String queueType, String throws ApiException { com.squareup.okhttp.Call call = getQueueConfigValidateBeforeCall(queueType, queueName, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -757,7 +757,7 @@ public Object getQueueNames() throws ApiException { */ private ApiResponse getQueueNamesWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = getQueueNamesValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -901,7 +901,7 @@ private ApiResponse putQueueConfigWithHttpInfo( String body, String queueType, String queueName) throws ApiException { com.squareup.okhttp.Call call = putQueueConfigValidateBeforeCall(body, queueType, queueName, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } diff --git a/src/main/java/io/orkes/conductor/client/http/api/GroupResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/GroupResourceApi.java index 8368f2c6..6861a6c7 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/GroupResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/GroupResourceApi.java @@ -26,7 +26,7 @@ import io.orkes.conductor.client.model.Group; import io.orkes.conductor.client.model.UpsertGroupRequest; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; public class GroupResourceApi { private ApiClient apiClient; @@ -408,7 +408,7 @@ private ApiResponse getGrantedPermissions1WithHttpInfo(St throws ApiException { com.squareup.okhttp.Call call = getGrantedPermissions1ValidateBeforeCall(groupId, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -523,7 +523,7 @@ public Group getGroup(String id) throws ApiException { */ private ApiResponse getGroupWithHttpInfo(String id) throws ApiException { com.squareup.okhttp.Call call = getGroupValidateBeforeCall(id, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -640,7 +640,7 @@ public List getUsersInGroup(String id) throws ApiException { private ApiResponse> getUsersInGroupWithHttpInfo(String id) throws ApiException { com.squareup.okhttp.Call call = getUsersInGroupValidateBeforeCall(id, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -743,7 +743,7 @@ public List listGroups() throws ApiException { */ private ApiResponse> listGroupsWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = listGroupsValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1001,7 +1001,7 @@ private ApiResponse upsertGroupWithHttpInfo( UpsertGroupRequest upsertGroupRequest, String id) throws ApiException { com.squareup.okhttp.Call call = upsertGroupValidateBeforeCall(upsertGroupRequest, id, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } } diff --git a/src/main/java/io/orkes/conductor/client/http/api/MetadataResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/MetadataResourceApi.java index 8a4e0110..86abcdd2 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/MetadataResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/MetadataResourceApi.java @@ -25,7 +25,8 @@ import io.orkes.conductor.client.ApiClient; import io.orkes.conductor.client.http.*; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; + public class MetadataResourceApi { private ApiClient apiClient; @@ -293,8 +294,7 @@ public WorkflowDef get(String name, Integer version, Boolean metadata) throws Ap private ApiResponse getWithHttpInfo(String name, Integer version, Boolean metadata) throws ApiException { com.squareup.okhttp.Call call = getValidateBeforeCall(name, version, metadata, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); - return apiClient.execute(call, localVarReturnType); + return apiClient.execute(call, WorkflowDef.class); } /** @@ -433,7 +433,7 @@ private ApiResponse> getAllWorkflowsWithHttpInfo( String access, Boolean metadata, String tagKey, String tagValue) throws ApiException { com.squareup.okhttp.Call call = getAllWorkflowsValidateBeforeCall(access, metadata, tagKey, tagValue, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -560,7 +560,7 @@ private ApiResponse getTaskDefWithHttpInfo(String tasktype, Boolean met throws ApiException { com.squareup.okhttp.Call call = getTaskDefValidateBeforeCall(tasktype, metadata, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -700,7 +700,7 @@ private ApiResponse> getTaskDefsWithHttpInfo( String access, Boolean metadata, String tagKey, String tagValue) throws ApiException { com.squareup.okhttp.Call call = getTaskDefsValidateBeforeCall(access, metadata, tagKey, tagValue, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } diff --git a/src/main/java/io/orkes/conductor/client/http/api/SchedulerResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/SchedulerResourceApi.java index bfd15dec..7088a52a 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/SchedulerResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/SchedulerResourceApi.java @@ -25,7 +25,8 @@ import io.orkes.conductor.client.model.SearchResultWorkflowScheduleExecutionModel; import io.orkes.conductor.client.model.WorkflowSchedule; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; + public class SchedulerResourceApi { private ApiClient apiClient; @@ -269,7 +270,7 @@ public List getAllSchedules(String workflowName) throws ApiExc private ApiResponse> getAllSchedulesWithHttpInfo(String workflowName) throws ApiException { com.squareup.okhttp.Call call = getAllSchedulesValidateBeforeCall(workflowName, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -421,7 +422,7 @@ private ApiResponse> getNextFewSchedulesWithHttpInfo( com.squareup.okhttp.Call call = getNextFewSchedulesValidateBeforeCall( cronExpression, scheduleStartTime, scheduleEndTime, limit, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -538,7 +539,7 @@ public WorkflowSchedule getSchedule(String name) throws ApiException { */ private ApiResponse getScheduleWithHttpInfo(String name) throws ApiException { com.squareup.okhttp.Call call = getScheduleValidateBeforeCall(name, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -642,7 +643,7 @@ public Map pauseAllSchedules() throws ApiException { */ private ApiResponse> pauseAllSchedulesWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = pauseAllSchedulesValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -862,7 +863,7 @@ public Map requeueAllExecutionRecords() throws ApiException { private ApiResponse> requeueAllExecutionRecordsWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = requeueAllExecutionRecordsValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -966,7 +967,7 @@ public Map resumeAllSchedules() throws ApiException { */ private ApiResponse> resumeAllSchedulesWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = resumeAllSchedulesValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1349,7 +1350,7 @@ private ApiResponse searchV22WithHtt com.squareup.okhttp.Call call = searchV22ValidateBeforeCall(start, size, sort, freeText, query, null, null); Type localVarReturnType = - new TypeToken() {}.getType(); + new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } diff --git a/src/main/java/io/orkes/conductor/client/http/api/SecretResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/SecretResourceApi.java index eb778ad8..fc64e6f6 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/SecretResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/SecretResourceApi.java @@ -20,7 +20,7 @@ import io.orkes.conductor.client.http.*; import io.orkes.conductor.client.model.TagObject; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; public class SecretResourceApi { private ApiClient apiClient; @@ -151,7 +151,7 @@ public void deleteSecret(String key) throws ApiException { */ private ApiResponse deleteSecretWithHttpInfo(String key) throws ApiException { com.squareup.okhttp.Call call = deleteSecretValidateBeforeCall(key, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -267,7 +267,7 @@ public String getSecret(String key) throws ApiException { */ private ApiResponse getSecretWithHttpInfo(String key) throws ApiException { com.squareup.okhttp.Call call = getSecretValidateBeforeCall(key, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -371,7 +371,7 @@ public Set listAllSecretNames() throws ApiException { */ private ApiResponse> listAllSecretNamesWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = listAllSecretNamesValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -477,7 +477,7 @@ private ApiResponse> listSecretsThatUserCanGrantAccessToWithHttpInf throws ApiException { com.squareup.okhttp.Call call = listSecretsThatUserCanGrantAccessToValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -600,7 +600,7 @@ public void putSecret(String body, String key) throws ApiException { */ private ApiResponse putSecretWithHttpInfo(String body, String key) throws ApiException { com.squareup.okhttp.Call call = putSecretValidateBeforeCall(body, key, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -716,7 +716,7 @@ public Boolean secretExists(String key) throws ApiException { */ private ApiResponse secretExistsWithHttpInfo(String key) throws ApiException { com.squareup.okhttp.Call call = secretExistsValidateBeforeCall(key, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } diff --git a/src/main/java/io/orkes/conductor/client/http/api/TagsApi.java b/src/main/java/io/orkes/conductor/client/http/api/TagsApi.java index 453fb20e..664d2c03 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/TagsApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/TagsApi.java @@ -24,7 +24,8 @@ import io.orkes.conductor.client.model.TagObject; import io.orkes.conductor.client.model.TagString; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; + public class TagsApi { private ApiClient apiClient; @@ -650,7 +651,7 @@ public List getTags() throws ApiException { */ private ApiResponse> getTagsWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = getTagsValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -769,7 +770,7 @@ public List getTaskTags(String taskName) throws ApiException { private ApiResponse> getTaskTagsWithHttpInfo(String taskName) throws ApiException { com.squareup.okhttp.Call call = getTaskTagsValidateBeforeCall(taskName, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -887,7 +888,7 @@ public List getWorkflowTags(String name) throws ApiException { private ApiResponse> getWorkflowTagsWithHttpInfo(String name) throws ApiException { com.squareup.okhttp.Call call = getWorkflowTagsValidateBeforeCall(name, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } diff --git a/src/main/java/io/orkes/conductor/client/http/api/TaskResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/TaskResourceApi.java index d03ffdbf..4dd0393b 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/TaskResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/TaskResourceApi.java @@ -34,7 +34,7 @@ import io.orkes.conductor.client.model.SearchResultTaskSummary; import com.amazonaws.util.EC2MetadataUtils; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; public class TaskResourceApi { private ApiClient apiClient; @@ -154,7 +154,7 @@ public Map all() throws ApiException { */ private ApiResponse> allWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = allValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -259,7 +259,7 @@ private ApiResponse>>> allVerboseWithH throws ApiException { com.squareup.okhttp.Call call = allVerboseValidateBeforeCall(null, null); Type localVarReturnType = - new TypeToken>>>() {}.getType(); + new TypeReference>>>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -416,7 +416,7 @@ private ApiResponse> batchPollWithHttpInfo( throws ApiException { com.squareup.okhttp.Call call = batchPollValidateBeforeCall(tasktype, workerid, domain, count, timeout, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -520,7 +520,7 @@ public List getAllPollData() throws ApiException { */ private ApiResponse> getAllPollDataWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = getAllPollDataValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -665,7 +665,7 @@ private ApiResponse getExternalStorageLocation1WithHttp com.squareup.okhttp.Call call = getExternalStorageLocation1ValidateBeforeCall( path, operation, payloadType, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -782,7 +782,7 @@ public List getPollData(String taskType) throws ApiException { private ApiResponse> getPollDataWithHttpInfo(String taskType) throws ApiException { com.squareup.okhttp.Call call = getPollDataValidateBeforeCall(taskType, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -900,7 +900,7 @@ public Task getTask(String taskId) throws ApiException { */ private ApiResponse getTaskWithHttpInfo(String taskId) throws ApiException { com.squareup.okhttp.Call call = getTaskValidateBeforeCall(taskId, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1019,7 +1019,7 @@ public List getTaskLogs(String taskId) throws ApiException { private ApiResponse> getTaskLogsWithHttpInfo(String taskId) throws ApiException { com.squareup.okhttp.Call call = getTaskLogsValidateBeforeCall(taskId, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1276,7 +1276,7 @@ private ApiResponse pollWithHttpInfo(String tasktype, String workerid, Str throws ApiException { com.squareup.okhttp.Call call = pollValidateBeforeCall(tasktype, workerid, domain, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1395,7 +1395,7 @@ public String requeuePendingTask(String taskType) throws ApiException { private ApiResponse requeuePendingTaskWithHttpInfo(String taskType) throws ApiException { com.squareup.okhttp.Call call = requeuePendingTaskValidateBeforeCall(taskType, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1547,7 +1547,7 @@ private ApiResponse search1WithHttpInfo( throws ApiException { com.squareup.okhttp.Call call = search1ValidateBeforeCall(start, size, sort, freeText, query, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1699,7 +1699,7 @@ private ApiResponse searchV21WithHttpInfo( throws ApiException { com.squareup.okhttp.Call call = searchV21ValidateBeforeCall(start, size, sort, freeText, query, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1812,7 +1812,7 @@ public Map size(List taskType) throws ApiException { private ApiResponse> sizeWithHttpInfo(List taskType) throws ApiException { com.squareup.okhttp.Call call = sizeValidateBeforeCall(taskType, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1925,7 +1925,7 @@ public String updateTask(TaskResult taskResult) throws ApiException { */ private ApiResponse updateTaskWithHttpInfo(TaskResult taskResult) throws ApiException { com.squareup.okhttp.Call call = updateTaskValidateBeforeCall(taskResult, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -2044,7 +2044,7 @@ private com.squareup.okhttp.Call updateTask1ValidateBeforeCall( public String updateTask1( Map body, String workflowId, String taskRefName, String status) throws ApiException { - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); ApiResponse resp = updateTask1WithHttpInfo(body, workflowId, taskRefName, status, false, localVarReturnType); return resp.getData(); } @@ -2059,7 +2059,7 @@ public String updateTask1( * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response */ public String updateTaskByRefName(Map output, String workflowId, String taskRefName, String status) throws ApiException { - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); ApiResponse resp = updateTask1WithHttpInfo(output, workflowId, taskRefName, status, false, localVarReturnType); return resp.getData(); } @@ -2074,7 +2074,7 @@ public String updateTaskByRefName(Map output, String workflowId, * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response */ public Workflow updateTaskSync(Map output, String workflowId, String taskRefName, String status) throws ApiException { - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); ApiResponse resp = updateTask1WithHttpInfo(output, workflowId, taskRefName, status, true, localVarReturnType); return resp.getData(); } @@ -2101,7 +2101,7 @@ private ApiResponse updateTaskSyncWithHttpInfo(Map bod throws ApiException { com.squareup.okhttp.Call call = updateTask1ValidateBeforeCall(body, workflowId, taskRefName, status, sync); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } diff --git a/src/main/java/io/orkes/conductor/client/http/api/TokenResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/TokenResourceApi.java index aadbff91..ffad070b 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/TokenResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/TokenResourceApi.java @@ -23,7 +23,7 @@ import io.orkes.conductor.client.http.*; import io.orkes.conductor.client.model.GenerateTokenRequest; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; public class TokenResourceApi { /** @@ -128,7 +128,7 @@ private static com.squareup.okhttp.Call generateTokenValidateBeforeCall( public static ApiResponse> generateTokenWithHttpInfo( ApiClient apiClient, GenerateTokenRequest generateTokenRequest) throws ApiException { com.squareup.okhttp.Call call = generateTokenValidateBeforeCall(apiClient, generateTokenRequest, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -224,7 +224,7 @@ private static com.squareup.okhttp.Call getUserInfoValidateBeforeCall( public static ApiResponse getUserInfoWithHttpInfo(ApiClient apiClient) throws ApiException { com.squareup.okhttp.Call call = getUserInfoValidateBeforeCall(apiClient, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } } diff --git a/src/main/java/io/orkes/conductor/client/http/api/UserResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/UserResourceApi.java index 5f697c5d..ecee3d0c 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/UserResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/UserResourceApi.java @@ -26,7 +26,7 @@ import io.orkes.conductor.client.model.Response; import io.orkes.conductor.client.model.UpsertUserRequest; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; public class UserResourceApi { private ApiClient apiClient; @@ -157,7 +157,7 @@ public void deleteUser(String id) throws ApiException { */ private ApiResponse deleteUserWithHttpInfo(String id) throws ApiException { com.squareup.okhttp.Call call = deleteUserValidateBeforeCall(id, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -276,7 +276,7 @@ public GrantedAccessResponse getGrantedPermissions(String userId) throws ApiExce private ApiResponse getGrantedPermissionsWithHttpInfo(String userId) throws ApiException { com.squareup.okhttp.Call call = getGrantedPermissionsValidateBeforeCall(userId, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -391,7 +391,7 @@ public ConductorUser getUser(String id) throws ApiException { */ private ApiResponse getUserWithHttpInfo(String id) throws ApiException { com.squareup.okhttp.Call call = getUserValidateBeforeCall(id, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -502,7 +502,7 @@ public List listUsers(Boolean apps) throws ApiException { private ApiResponse> listUsersWithHttpInfo(Boolean apps) throws ApiException { com.squareup.okhttp.Call call = listUsersValidateBeforeCall(apps, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -622,7 +622,7 @@ private ApiResponse sendInviteEmailWithHttpInfo(String id, ConductorUser throws ApiException { com.squareup.okhttp.Call call = sendInviteEmailValidateBeforeCall(id, conductorUser, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -750,7 +750,7 @@ private ApiResponse upsertUserWithHttpInfo( UpsertUserRequest upsertUserRequest, String id) throws ApiException { com.squareup.okhttp.Call call = upsertUserValidateBeforeCall(upsertUserRequest, id, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } } diff --git a/src/main/java/io/orkes/conductor/client/http/api/WorkflowBulkResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/WorkflowBulkResourceApi.java index 21a14bf6..fe24b7d9 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/WorkflowBulkResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/WorkflowBulkResourceApi.java @@ -24,7 +24,7 @@ import io.orkes.conductor.client.ApiClient; import io.orkes.conductor.client.http.*; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; public class WorkflowBulkResourceApi { private ApiClient apiClient; @@ -155,7 +155,7 @@ public BulkResponse pauseWorkflow1(List workflowIds) throws ApiException private ApiResponse pauseWorkflow1WithHttpInfo(List workflowIds) throws ApiException { com.squareup.okhttp.Call call = pauseWorkflow1ValidateBeforeCall(workflowIds, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } /** @@ -282,7 +282,7 @@ private ApiResponse restart1WithHttpInfo( List workflowIds, Boolean useLatestDefinitions) throws ApiException { com.squareup.okhttp.Call call = restart1ValidateBeforeCall(workflowIds, useLatestDefinitions, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -396,7 +396,7 @@ public BulkResponse resumeWorkflow1(List workflowIds) throws ApiExceptio private ApiResponse resumeWorkflow1WithHttpInfo(List workflowIds) throws ApiException { com.squareup.okhttp.Call call = resumeWorkflow1ValidateBeforeCall(workflowIds, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -510,7 +510,7 @@ public BulkResponse retry1(List workflowIds) throws ApiException { private ApiResponse retry1WithHttpInfo(List workflowIds) throws ApiException { com.squareup.okhttp.Call call = retry1ValidateBeforeCall(workflowIds, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -636,7 +636,7 @@ private ApiResponse terminateWithHttpInfo(List workflowIds throws ApiException { com.squareup.okhttp.Call call = terminateValidateBeforeCall(workflowIds, reason, triggerFailureWorkflow, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } } diff --git a/src/main/java/io/orkes/conductor/client/http/api/WorkflowResourceApi.java b/src/main/java/io/orkes/conductor/client/http/api/WorkflowResourceApi.java index ee73a067..baedc245 100644 --- a/src/main/java/io/orkes/conductor/client/http/api/WorkflowResourceApi.java +++ b/src/main/java/io/orkes/conductor/client/http/api/WorkflowResourceApi.java @@ -14,20 +14,24 @@ import java.io.IOException; import java.lang.reflect.Type; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import com.netflix.conductor.common.metadata.workflow.RerunWorkflowRequest; import com.netflix.conductor.common.metadata.workflow.SkipTaskRequest; import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest; import com.netflix.conductor.common.run.Workflow; +import com.netflix.conductor.common.run.WorkflowTestRequest; -import com.squareup.okhttp.Call; import io.orkes.conductor.client.ApiClient; import io.orkes.conductor.client.http.*; import io.orkes.conductor.client.model.*; import io.orkes.conductor.common.model.WorkflowRun; -import com.google.gson.reflect.TypeToken; +import com.fasterxml.jackson.core.type.TypeReference; +import com.squareup.okhttp.Call; public class WorkflowResourceApi { private ApiClient apiClient; @@ -122,7 +126,7 @@ public ApiResponse executeWorkflowWithHttpInfo( com.squareup.okhttp.Call call = executeWorkflowValidateBeforeCall( body, name, version, waitUntilTaskRef, requestId, waitForSeconds,null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -187,7 +191,7 @@ public ApiResponse executeWorkflowWithHttpInfo( com.squareup.okhttp.Call call = executeWorkflowValidateBeforeCall( body, name, version, waitUntilTaskRef, requestId, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -438,7 +442,7 @@ public void onRequestProgress( requestId, progressListener, progressRequestListener); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); apiClient.executeAsync(call, localVarReturnType, callback); return call; @@ -811,7 +815,7 @@ private ApiResponse getExecutionStatusWithHttpInfo( String workflowId, Boolean includeTasks) throws ApiException { com.squareup.okhttp.Call call = getExecutionStatusValidateBeforeCall(workflowId, includeTasks, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -956,7 +960,7 @@ private ApiResponse getExternalStorageLocationWithHttpI com.squareup.okhttp.Call call = getExternalStorageLocationValidateBeforeCall( path, operation, payloadType, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1104,7 +1108,7 @@ private ApiResponse> getRunningWorkflowWithHttpInfo( String name, Integer version, Long startTime, Long endTime) throws ApiException { com.squareup.okhttp.Call call = getRunningWorkflowValidateBeforeCall(name, version, startTime, endTime, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1249,7 +1253,7 @@ private ApiResponse getWorkflowStatusSummaryWithHttpInfo( com.squareup.okhttp.Call call = getWorkflowStatusSummaryValidateBeforeCall( workflowId, includeOutput, includeVariables, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1401,7 +1405,7 @@ private ApiResponse>> getWorkflowsWithHttpInfo( throws ApiException { com.squareup.okhttp.Call call = getWorkflowsValidateBeforeCall(body, name, includeClosed, includeTasks, null, null); - Type localVarReturnType = new TypeToken>>() {}.getType(); + Type localVarReturnType = new TypeReference>>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1502,7 +1506,7 @@ public com.squareup.okhttp.Response intercept( */ public Map> getWorkflowsByNamesAndCorrelationIds(CorrelationIdsSearchRequest request, Boolean includeClosed, Boolean includeTasks) throws ApiException { com.squareup.okhttp.Call call = getWorkflowsByNamesAndCorrelationIdsBeforeCall(request, includeClosed, includeTasks, null, null); - Type localVarReturnType = new TypeToken>>(){}.getType(); + Type localVarReturnType = new TypeReference>>(){}.getType(); ApiResponse>> response = apiClient.execute(call, localVarReturnType); return response.getData(); } @@ -1637,7 +1641,7 @@ private ApiResponse> getWorkflows1WithHttpInfo( com.squareup.okhttp.Call call = getWorkflows1ValidateBeforeCall( name, correlationId, includeClosed, includeTasks, null, null); - Type localVarReturnType = new TypeToken>() {}.getType(); + Type localVarReturnType = new TypeReference>() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -1887,7 +1891,7 @@ private ApiResponse rerunWithHttpInfo( RerunWorkflowRequest rerunWorkflowRequest, String workflowId) throws ApiException { com.squareup.okhttp.Call call = rerunValidateBeforeCall(rerunWorkflowRequest, workflowId, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -2561,7 +2565,7 @@ private ApiResponse searchWithHttpInfo( searchValidateBeforeCall( queryId, start, size, sort, freeText, query, skipCache, null, null); Type localVarReturnType = - new TypeToken() {}.getType(); + new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -2713,7 +2717,7 @@ private ApiResponse searchV2WithHttpInfo( throws ApiException { com.squareup.okhttp.Call call = searchV2ValidateBeforeCall(start, size, sort, freeText, query, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -2866,7 +2870,7 @@ private ApiResponse searchWorkflowsByTasksWithHttpI com.squareup.okhttp.Call call = searchWorkflowsByTasksValidateBeforeCall( start, size, sort, freeText, query, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -3019,7 +3023,7 @@ private ApiResponse searchWorkflowsByTasksV2WithHttpInfo( com.squareup.okhttp.Call call = searchWorkflowsByTasksV2ValidateBeforeCall( start, size, sort, freeText, query, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -3376,14 +3380,14 @@ private ApiResponse startWorkflowWithHttpInfo(StartWorkflowRequest start throws ApiException { com.squareup.okhttp.Call call = startWorkflowValidateBeforeCall(startWorkflowRequest, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } private ApiResponse testWorkflowWithHttpInfo(WorkflowTestRequest testRequest) throws ApiException { com.squareup.okhttp.Call call = testWorkflowValidateBeforeCall(testRequest, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -3554,7 +3558,7 @@ private ApiResponse startWorkflow1WithHttpInfo( com.squareup.okhttp.Call call = startWorkflow1ValidateBeforeCall( body, name, version, correlationId, priority, null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } @@ -3787,13 +3791,13 @@ public Object uploadCompletedWorkflows() throws ApiException { */ private ApiResponse uploadCompletedWorkflowsWithHttpInfo() throws ApiException { com.squareup.okhttp.Call call = uploadCompletedWorkflowsValidateBeforeCall(null, null); - Type localVarReturnType = new TypeToken() {}.getType(); + Type localVarReturnType = new TypeReference() {}.getType(); return apiClient.execute(call, localVarReturnType); } public Workflow updateVariables(String workflowId, Map variables) { com.squareup.okhttp.Call call = updateVariablesCall(workflowId, variables); - Type returnType = new TypeToken() {}.getType(); + Type returnType = new TypeReference() {}.getType(); ApiResponse response = apiClient.execute(call, returnType); return response.getData(); } diff --git a/src/main/java/io/orkes/conductor/client/model/Action.java b/src/main/java/io/orkes/conductor/client/model/Action.java index f71ce25c..f321e7b2 100644 --- a/src/main/java/io/orkes/conductor/client/model/Action.java +++ b/src/main/java/io/orkes/conductor/client/model/Action.java @@ -12,20 +12,14 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.Objects; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** Action */ public class Action { /** Gets or Sets action */ - @JsonAdapter(ActionEnum.Adapter.class) public enum ActionEnum { START_WORKFLOW("start_workflow"), COMPLETE_TASK("complete_task"), @@ -56,20 +50,6 @@ public static ActionEnum fromValue(String input) { } return null; } - - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final ActionEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public ActionEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return ActionEnum.fromValue((String) (value)); - } - } } @SerializedName("action") diff --git a/src/main/java/io/orkes/conductor/client/model/AuthorizationRequest.java b/src/main/java/io/orkes/conductor/client/model/AuthorizationRequest.java index 4a1376cb..0d19ce03 100644 --- a/src/main/java/io/orkes/conductor/client/model/AuthorizationRequest.java +++ b/src/main/java/io/orkes/conductor/client/model/AuthorizationRequest.java @@ -12,22 +12,16 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** AuthorizationRequest */ public class AuthorizationRequest { /** The set of access which is granted or removed */ - @JsonAdapter(AccessEnum.Adapter.class) public enum AccessEnum { CREATE("CREATE"), READ("READ"), @@ -58,20 +52,6 @@ public static AccessEnum fromValue(String input) { } return null; } - - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final AccessEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public AccessEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return AccessEnum.fromValue((String) (value)); - } - } } @SerializedName("access") diff --git a/src/main/java/io/orkes/conductor/client/model/GrantedAccess.java b/src/main/java/io/orkes/conductor/client/model/GrantedAccess.java index 881d9a87..fe1d9d6c 100644 --- a/src/main/java/io/orkes/conductor/client/model/GrantedAccess.java +++ b/src/main/java/io/orkes/conductor/client/model/GrantedAccess.java @@ -12,22 +12,16 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** GrantedAccess */ public class GrantedAccess { /** Gets or Sets access */ - @JsonAdapter(AccessEnum.Adapter.class) public enum AccessEnum { CREATE("CREATE"), READ("READ"), @@ -58,20 +52,6 @@ public static AccessEnum fromValue(String input) { } return null; } - - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final AccessEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public AccessEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return AccessEnum.fromValue((String) (value)); - } - } } @SerializedName("access") diff --git a/src/main/java/io/orkes/conductor/client/model/Group.java b/src/main/java/io/orkes/conductor/client/model/Group.java index 9ca4c1d9..3979f053 100644 --- a/src/main/java/io/orkes/conductor/client/model/Group.java +++ b/src/main/java/io/orkes/conductor/client/model/Group.java @@ -12,20 +12,14 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.*; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** Group */ public class Group { /** Gets or Sets inner */ - @JsonAdapter(InnerEnum.Adapter.class) public enum InnerEnum { CREATE("CREATE"), READ("READ"), @@ -56,20 +50,6 @@ public static InnerEnum fromValue(String input) { } return null; } - - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final InnerEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public InnerEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return InnerEnum.fromValue((String) (value)); - } - } } @SerializedName("defaultAccess") diff --git a/src/main/java/io/orkes/conductor/client/model/Subject.java b/src/main/java/io/orkes/conductor/client/model/Subject.java index 7f6718cc..4defe3ea 100644 --- a/src/main/java/io/orkes/conductor/client/model/Subject.java +++ b/src/main/java/io/orkes/conductor/client/model/Subject.java @@ -12,14 +12,9 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.Objects; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** Subject */ @@ -28,7 +23,6 @@ public class Subject { private String id = null; /** Gets or Sets type */ - @JsonAdapter(TypeEnum.Adapter.class) public enum TypeEnum { USER("USER"), ROLE("ROLE"), @@ -57,20 +51,6 @@ public static TypeEnum fromValue(String input) { } return null; } - - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final TypeEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public TypeEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return TypeEnum.fromValue((String) (value)); - } - } } @SerializedName("type") diff --git a/src/main/java/io/orkes/conductor/client/model/SubjectRef.java b/src/main/java/io/orkes/conductor/client/model/SubjectRef.java index 2d0b54b2..e7888d4e 100644 --- a/src/main/java/io/orkes/conductor/client/model/SubjectRef.java +++ b/src/main/java/io/orkes/conductor/client/model/SubjectRef.java @@ -12,14 +12,9 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.Objects; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** User, group or role which is granted/removed access */ @@ -29,7 +24,6 @@ public class SubjectRef { private String id = null; /** User, role or group */ - @JsonAdapter(TypeEnum.Adapter.class) public enum TypeEnum { USER("USER"), ROLE("ROLE"), @@ -59,20 +53,6 @@ public static TypeEnum fromValue(String input) { } return null; } - - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final TypeEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public TypeEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return TypeEnum.fromValue((String) (value)); - } - } } @SerializedName("type") diff --git a/src/main/java/io/orkes/conductor/client/model/TagObject.java b/src/main/java/io/orkes/conductor/client/model/TagObject.java index 3192e6cb..6a487301 100644 --- a/src/main/java/io/orkes/conductor/client/model/TagObject.java +++ b/src/main/java/io/orkes/conductor/client/model/TagObject.java @@ -12,14 +12,9 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.Objects; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** TagObject */ @@ -28,7 +23,6 @@ public class TagObject { private String key = null; /** Gets or Sets type */ - @JsonAdapter(TypeEnum.Adapter.class) public enum TypeEnum { METADATA("METADATA"), RATE_LIMIT("RATE_LIMIT"); @@ -57,19 +51,7 @@ public static TypeEnum fromValue(String input) { return null; } - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final TypeEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - @Override - public TypeEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return TypeEnum.fromValue((String) (value)); - } - } } @SerializedName("type") diff --git a/src/main/java/io/orkes/conductor/client/model/TagString.java b/src/main/java/io/orkes/conductor/client/model/TagString.java index 350007d1..0154b07e 100644 --- a/src/main/java/io/orkes/conductor/client/model/TagString.java +++ b/src/main/java/io/orkes/conductor/client/model/TagString.java @@ -12,14 +12,9 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.Objects; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** TagString */ @@ -28,7 +23,6 @@ public class TagString { private String key = null; /** Gets or Sets type */ - @JsonAdapter(TypeEnum.Adapter.class) public enum TypeEnum { METADATA("METADATA"), RATE_LIMIT("RATE_LIMIT"); @@ -57,19 +51,6 @@ public static TypeEnum fromValue(String input) { return null; } - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final TypeEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public TypeEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return TypeEnum.fromValue((String) (value)); - } - } } @SerializedName("type") diff --git a/src/main/java/io/orkes/conductor/client/model/TargetRef.java b/src/main/java/io/orkes/conductor/client/model/TargetRef.java index e263921a..695a9efb 100644 --- a/src/main/java/io/orkes/conductor/client/model/TargetRef.java +++ b/src/main/java/io/orkes/conductor/client/model/TargetRef.java @@ -12,14 +12,9 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.Objects; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** @@ -33,7 +28,6 @@ public class TargetRef { /** * Gets or Sets type */ - @JsonAdapter(TypeEnum.Adapter.class) public enum TypeEnum { WORKFLOW_DEF("WORKFLOW_DEF"), TASK_DEF("TASK_DEF"), @@ -66,19 +60,6 @@ public static TypeEnum fromValue(String input) { } return null; } - - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final TypeEnum enumeration) throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public TypeEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return TypeEnum.fromValue((String) (value)); - } - } } @SerializedName("type") diff --git a/src/main/java/io/orkes/conductor/client/model/UpsertGroupRequest.java b/src/main/java/io/orkes/conductor/client/model/UpsertGroupRequest.java index c22f7f2d..f3950631 100644 --- a/src/main/java/io/orkes/conductor/client/model/UpsertGroupRequest.java +++ b/src/main/java/io/orkes/conductor/client/model/UpsertGroupRequest.java @@ -12,14 +12,9 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.*; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** UpsertGroupRequest */ @@ -28,7 +23,6 @@ public class UpsertGroupRequest { * a default Map<TargetType, Set<Access> to share permissions, allowed target types: * WORKFLOW_DEF, TASK_DEF */ - @JsonAdapter(InnerEnum.Adapter.class) public enum InnerEnum { CREATE("CREATE"), READ("READ"), @@ -60,19 +54,6 @@ public static InnerEnum fromValue(String input) { return null; } - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final InnerEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public InnerEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return InnerEnum.fromValue((String) (value)); - } - } } @SerializedName("defaultAccess") @@ -82,7 +63,6 @@ public InnerEnum read(final JsonReader jsonReader) throws IOException { private String description = null; /** Gets or Sets roles */ - @JsonAdapter(RolesEnum.Adapter.class) public enum RolesEnum { ADMIN("ADMIN"), USER("USER"), @@ -114,19 +94,6 @@ public static RolesEnum fromValue(String input) { return null; } - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final RolesEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public RolesEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return RolesEnum.fromValue((String) (value)); - } - } } @SerializedName("roles") diff --git a/src/main/java/io/orkes/conductor/client/model/UpsertUserRequest.java b/src/main/java/io/orkes/conductor/client/model/UpsertUserRequest.java index 0b5f0fbc..39ce1cc9 100644 --- a/src/main/java/io/orkes/conductor/client/model/UpsertUserRequest.java +++ b/src/main/java/io/orkes/conductor/client/model/UpsertUserRequest.java @@ -12,16 +12,11 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** UpsertUserRequest */ @@ -33,7 +28,6 @@ public class UpsertUserRequest { private String name = null; /** Gets or Sets roles */ - @JsonAdapter(RolesEnum.Adapter.class) public enum RolesEnum { ADMIN("ADMIN"), USER("USER"), @@ -64,20 +58,6 @@ public static RolesEnum fromValue(String input) { } return null; } - - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final RolesEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public RolesEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return RolesEnum.fromValue((String) (value)); - } - } } @SerializedName("roles") diff --git a/src/main/java/io/orkes/conductor/client/model/WorkflowScheduleExecutionModel.java b/src/main/java/io/orkes/conductor/client/model/WorkflowScheduleExecutionModel.java index bada2350..e4581356 100644 --- a/src/main/java/io/orkes/conductor/client/model/WorkflowScheduleExecutionModel.java +++ b/src/main/java/io/orkes/conductor/client/model/WorkflowScheduleExecutionModel.java @@ -12,16 +12,11 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.Objects; import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** WorkflowScheduleExecutionModel */ @@ -48,7 +43,6 @@ public class WorkflowScheduleExecutionModel { private StartWorkflowRequest startWorkflowRequest = null; /** Gets or Sets state */ - @JsonAdapter(StateEnum.Adapter.class) public enum StateEnum { POLLED("POLLED"), FAILED("FAILED"), @@ -77,20 +71,6 @@ public static StateEnum fromValue(String input) { } return null; } - - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final StateEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public StateEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return StateEnum.fromValue((String) (value)); - } - } } @SerializedName("state") diff --git a/src/main/java/io/orkes/conductor/client/model/WorkflowStatus.java b/src/main/java/io/orkes/conductor/client/model/WorkflowStatus.java index b8460906..91104f5e 100644 --- a/src/main/java/io/orkes/conductor/client/model/WorkflowStatus.java +++ b/src/main/java/io/orkes/conductor/client/model/WorkflowStatus.java @@ -12,16 +12,11 @@ */ package io.orkes.conductor.client.model; -import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Objects; -import com.google.gson.TypeAdapter; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.SerializedName; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; import io.swagger.v3.oas.annotations.media.Schema; /** WorkflowStatus */ @@ -33,7 +28,6 @@ public class WorkflowStatus { private Map output = null; /** Gets or Sets status */ - @JsonAdapter(StatusEnum.Adapter.class) public enum StatusEnum { RUNNING("RUNNING"), COMPLETED("COMPLETED"), @@ -65,20 +59,6 @@ public static StatusEnum fromValue(String input) { } return null; } - - public static class Adapter extends TypeAdapter { - @Override - public void write(final JsonWriter jsonWriter, final StatusEnum enumeration) - throws IOException { - jsonWriter.value(String.valueOf(enumeration.getValue())); - } - - @Override - public StatusEnum read(final JsonReader jsonReader) throws IOException { - Object value = jsonReader.nextString(); - return StatusEnum.fromValue((String) (value)); - } - } } @SerializedName("status") diff --git a/src/main/java/io/orkes/conductor/client/model/WorkflowTestRequest.java b/src/main/java/io/orkes/conductor/client/model/WorkflowTestRequest.java deleted file mode 100644 index 30d6ef3f..00000000 --- a/src/main/java/io/orkes/conductor/client/model/WorkflowTestRequest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2023 Orkes, Inc. - *

- * Licensed 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 io.orkes.conductor.client.model; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.netflix.conductor.common.metadata.tasks.Task; -import com.netflix.conductor.common.metadata.tasks.TaskResult; -import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -@Data -@Slf4j -public class WorkflowTestRequest extends StartWorkflowRequest { - - //Map of task reference name to mock output for the task - private Map> taskRefToMockOutput = new HashMap<>(); - - //If there are sub-workflows inside the workflow - //The map of task reference name to the mock for the sub-workflow - private Map subWorkflowTestRequest = new HashMap<>(); - - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class TaskMock { - private TaskResult.Status status = TaskResult.Status.COMPLETED; - private Map output = new HashMap<>(); - //Time in millis for the execution of the task. - //Set this value to view the execution timeline view and also trigger any timeouts associated with the tasks - private long executionTime; - - private long queueWaitTime; - - public TaskMock(TaskResult.Status status, Map output) { - this.status = status; - this.output = output; - } - - public TaskMock(Task.Status status, Map output, long executionTime, long queueWaitTime) { - try { - this.status = TaskResult.Status.valueOf(status.name()); - } catch (IllegalArgumentException invalidValue) { - this.status = TaskResult.Status.IN_PROGRESS; - } - this.output = output; - this.executionTime = executionTime; - this.queueWaitTime = queueWaitTime; - } - } - -} diff --git a/src/main/java/io/orkes/conductor/client/model/event/QueueConfiguration.java b/src/main/java/io/orkes/conductor/client/model/event/QueueConfiguration.java index 5b1962a3..83e1fc24 100644 --- a/src/main/java/io/orkes/conductor/client/model/event/QueueConfiguration.java +++ b/src/main/java/io/orkes/conductor/client/model/event/QueueConfiguration.java @@ -14,11 +14,10 @@ import java.util.Map; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; +import io.orkes.conductor.client.http.JSON; public abstract class QueueConfiguration { - private static final Gson gson = new GsonBuilder().create(); + private static final JSON json = new JSON(); private final String queueName; private final String queueType; @@ -49,6 +48,7 @@ public String getQueueName() { return this.queueName; } + @Deprecated public String getConfiguration() throws Exception { if (this.consumer == null) { throw new RuntimeException("consumer must be set"); @@ -60,6 +60,20 @@ public String getConfiguration() throws Exception { Map.of( "consumer", this.consumer.getConfiguration(), "producer", this.producer.getConfiguration()); - return gson.toJson(config); + return json.serialize(config); + } + + public Map getQueueConfiguration() throws Exception { + if (this.consumer == null) { + throw new RuntimeException("consumer must be set"); + } + if (this.producer == null) { + throw new RuntimeException("producer must be set"); + } + Map config = + Map.of( + "consumer", this.consumer.getConfiguration(), + "producer", this.producer.getConfiguration()); + return config; } } diff --git a/src/main/java/io/orkes/conductor/client/spring/ApiClientAutoConfiguration.java b/src/main/java/io/orkes/conductor/client/spring/ApiClientAutoConfiguration.java new file mode 100644 index 00000000..acc014a1 --- /dev/null +++ b/src/main/java/io/orkes/conductor/client/spring/ApiClientAutoConfiguration.java @@ -0,0 +1,72 @@ +/* + * Copyright 2020 Orkes, Inc. + *

+ * Licensed 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 io.orkes.conductor.client.spring; + + + +import org.apache.commons.lang3.StringUtils; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import io.orkes.conductor.client.ApiClient; + +import lombok.extern.slf4j.Slf4j; + +@Configuration(proxyBeanMethods = false) +@Slf4j +public class ApiClientAutoConfiguration { + + public static final String CONDUCTOR_SERVER_URL = "conductor.server.url"; + public static final String CONDUCTOR_CLIENT_KEY_ID = "conductor.security.client.key-id"; + public static final String CONDUCTOR_CLIENT_SECRET = "conductor.security.client.secret"; + public static final String CONDUCTOR_GRPC_SERVER = "conductor.grpc.host"; + + public static final String CONDUCTOR_GRPC_PORT = "conductor.grpc.port"; + + public static final String CONDUCTOR_GRPC_SSL = "conductor.grpc.ssl"; + + @Bean + public ApiClient getApiClient(Environment env) { + String rootUri = env.getProperty(CONDUCTOR_SERVER_URL); + String keyId = env.getProperty(CONDUCTOR_CLIENT_KEY_ID); + String secret = env.getProperty(CONDUCTOR_CLIENT_SECRET); + if (rootUri.endsWith("/")) { + rootUri = rootUri.substring(0, rootUri.length() - 1); + } + if (StringUtils.isNotBlank(keyId) && StringUtils.isNotBlank(secret)) { + ApiClient apiClient = new ApiClient(rootUri, keyId, secret); + apiClient = configureGrpc(apiClient, env); + return apiClient; + } + + ApiClient apiClient = new ApiClient(rootUri); + apiClient = configureGrpc(apiClient, env); + return apiClient; + } + + private ApiClient configureGrpc(ApiClient apiClient, Environment env) { + + String grpcHost = env.getProperty(CONDUCTOR_GRPC_SERVER); + String grpcPort = env.getProperty(CONDUCTOR_GRPC_PORT); + boolean useSSL = Boolean.parseBoolean(env.getProperty(CONDUCTOR_GRPC_SSL)); + if (StringUtils.isNotBlank(grpcHost)) { + log.info("Using gRPC for worker communication. Server {}, port {}, using SSL? {}", grpcHost, grpcPort, useSSL); + int port = Integer.parseInt(grpcPort); + apiClient.setUseGRPC(grpcHost, port); + apiClient.setUseSSL(useSSL); + } + return apiClient; + } + +} diff --git a/src/main/java/io/orkes/conductor/client/spring/OrkesAnnotatedWorkerExecutor.java b/src/main/java/io/orkes/conductor/client/spring/OrkesAnnotatedWorkerExecutor.java new file mode 100644 index 00000000..8a587548 --- /dev/null +++ b/src/main/java/io/orkes/conductor/client/spring/OrkesAnnotatedWorkerExecutor.java @@ -0,0 +1,62 @@ +/* + * Copyright 2023 Orkes, Inc. + *

+ * Licensed 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 io.orkes.conductor.client.spring; + +import com.netflix.conductor.sdk.workflow.executor.task.AnnotatedWorkerExecutor; +import com.netflix.conductor.sdk.workflow.executor.task.WorkerConfiguration; + +import io.orkes.conductor.client.TaskClient; +import io.orkes.conductor.client.automator.TaskRunnerConfigurer; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class OrkesAnnotatedWorkerExecutor extends AnnotatedWorkerExecutor { + + private TaskClient taskClient; + + private TaskRunnerConfigurer taskRunner; + + public OrkesAnnotatedWorkerExecutor(TaskClient taskClient, WorkerConfiguration workerConfiguration) { + super(taskClient, workerConfiguration); + this.taskClient = taskClient; + } + + + @Override + public void shutdown() { + if(this.taskRunner != null) { + this.taskRunner.shutdown(); + } + } + + @Override + public void startPolling() { + + if (executors.isEmpty()) { + return; + } + + log.info("Starting workers with threadCount {}", workerToThreadCount); + log.info("Worker domains {}", workerDomains); + + this.taskRunner = new TaskRunnerConfigurer.Builder(this.taskClient, executors) + .withTaskThreadCount(workerToThreadCount) + .withTaskToDomain(workerDomains) + .withTaskPollTimeout(5) + .build(); + + taskRunner.init(); + + } +} diff --git a/src/main/java/io/orkes/conductor/client/spring/OrkesConductorClientAutoConfiguration.java b/src/main/java/io/orkes/conductor/client/spring/OrkesConductorClientAutoConfiguration.java new file mode 100644 index 00000000..13b98804 --- /dev/null +++ b/src/main/java/io/orkes/conductor/client/spring/OrkesConductorClientAutoConfiguration.java @@ -0,0 +1,57 @@ +/* + * Copyright 2020 Orkes, Inc. + *

+ * Licensed 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 io.orkes.conductor.client.spring; + + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.netflix.conductor.sdk.workflow.executor.WorkflowExecutor; +import com.netflix.conductor.sdk.workflow.executor.task.AnnotatedWorkerExecutor; +import com.netflix.conductor.sdk.workflow.executor.task.WorkerConfiguration; + +import io.orkes.conductor.client.ApiClient; +import io.orkes.conductor.client.OrkesClients; +import io.orkes.conductor.client.TaskClient; +import io.orkes.conductor.client.http.OrkesTaskClient; + +import lombok.extern.slf4j.Slf4j; + +@Configuration(proxyBeanMethods = false) +@Slf4j +public class OrkesConductorClientAutoConfiguration { + + @Bean + public TaskClient taskClient(ApiClient apiClient) { + TaskClient taskClient = new OrkesTaskClient(apiClient); + return taskClient; + } + + @Bean + public WorkflowExecutor getWorkflowExecutor(ApiClient apiClient, AnnotatedWorkerExecutor annotatedWorkerExecutor) { + OrkesClients clients = new OrkesClients(apiClient); + return new WorkflowExecutor( + clients.getTaskClient(), + clients.getWorkflowClient(), + clients.getMetadataClient(), + annotatedWorkerExecutor + ); + } + + @Bean + public AnnotatedWorkerExecutor annotatedWorkerExecutor( + TaskClient taskClient, WorkerConfiguration workerConfiguration) { + return new OrkesAnnotatedWorkerExecutor(taskClient, workerConfiguration); + } +} diff --git a/src/main/java/io/orkes/conductor/client/spring/OrkesConductorWorkerAutoConfiguration.java b/src/main/java/io/orkes/conductor/client/spring/OrkesConductorWorkerAutoConfiguration.java new file mode 100644 index 00000000..d7edd911 --- /dev/null +++ b/src/main/java/io/orkes/conductor/client/spring/OrkesConductorWorkerAutoConfiguration.java @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Orkes, Inc. + *

+ * Licensed 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 io.orkes.conductor.client.spring; + +import java.util.Map; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.stereotype.Component; + +import com.netflix.conductor.client.http.TaskClient; +import com.netflix.conductor.sdk.workflow.executor.task.AnnotatedWorkerExecutor; + +@Component +public class OrkesConductorWorkerAutoConfiguration implements ApplicationListener { + + private final TaskClient taskClient; + + private final AnnotatedWorkerExecutor annotatedWorkerExecutor; + + public OrkesConductorWorkerAutoConfiguration( + TaskClient taskClient, AnnotatedWorkerExecutor annotatedWorkerExecutor) { + this.taskClient = taskClient; + this.annotatedWorkerExecutor = annotatedWorkerExecutor; + } + + @Override + public void onApplicationEvent(ContextRefreshedEvent refreshedEvent) { + ApplicationContext applicationContext = refreshedEvent.getApplicationContext(); + Map beans = applicationContext.getBeansWithAnnotation(Component.class); + beans.values() + .forEach( + bean -> { + annotatedWorkerExecutor.addBean(bean); + }); + annotatedWorkerExecutor.startPolling(); + } +} diff --git a/src/main/java/io/orkes/conductor/client/spring/OrkesSpringWorkerConfiguration.java b/src/main/java/io/orkes/conductor/client/spring/OrkesSpringWorkerConfiguration.java new file mode 100644 index 00000000..838dd7d1 --- /dev/null +++ b/src/main/java/io/orkes/conductor/client/spring/OrkesSpringWorkerConfiguration.java @@ -0,0 +1,46 @@ +/* + * Copyright 2023 Orkes, Inc. + *

+ * Licensed 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 io.orkes.conductor.client.spring; + +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import com.netflix.conductor.sdk.workflow.executor.task.WorkerConfiguration; + +@Component +public class OrkesSpringWorkerConfiguration extends WorkerConfiguration { + + private final Environment environment; + + public OrkesSpringWorkerConfiguration(Environment environment) { + this.environment = environment; + } + + @Override + public int getPollingInterval(String taskName) { + String key = "conductor.worker." + taskName + ".pollingInterval"; + return environment.getProperty(key, Integer.class, 0); + } + + @Override + public int getThreadCount(String taskName) { + String key = "conductor.worker." + taskName + ".threadCount"; + return environment.getProperty(key, Integer.class, 0); + } + + @Override + public String getDomain(String taskName) { + String key = "conductor.worker." + taskName + ".domain"; + return environment.getProperty(key, String.class, null); + } +} diff --git a/src/test/java/io/orkes/conductor/client/LocalWorkerTest.java b/src/test/java/io/orkes/conductor/client/LocalWorkerTest.java index 18f870e0..5cf344a1 100644 --- a/src/test/java/io/orkes/conductor/client/LocalWorkerTest.java +++ b/src/test/java/io/orkes/conductor/client/LocalWorkerTest.java @@ -25,8 +25,6 @@ public class LocalWorkerTest { public static void main(String[] args) { ApiClient apiClient = new ApiClient("http://localhost:8080/api"); - apiClient.setUseGRPC("localhost", 8090); - OrkesClients clients = new OrkesClients(apiClient); TaskClient taskClient = clients.getTaskClient(); diff --git a/src/test/java/io/orkes/conductor/client/api/ClientTest.java b/src/test/java/io/orkes/conductor/client/api/ClientTest.java index 144335bb..81171714 100644 --- a/src/test/java/io/orkes/conductor/client/api/ClientTest.java +++ b/src/test/java/io/orkes/conductor/client/api/ClientTest.java @@ -16,9 +16,9 @@ import io.orkes.conductor.client.util.ApiUtil; public abstract class ClientTest { - protected final OrkesClients orkesClients; + protected static OrkesClients orkesClients; - public ClientTest() { - this.orkesClients = ApiUtil.getOrkesClient(); + static { + orkesClients = ApiUtil.getOrkesClient(); } } diff --git a/src/test/java/io/orkes/conductor/client/api/MetadataClientTests.java b/src/test/java/io/orkes/conductor/client/api/MetadataClientTests.java index e9941461..f58830af 100644 --- a/src/test/java/io/orkes/conductor/client/api/MetadataClientTests.java +++ b/src/test/java/io/orkes/conductor/client/api/MetadataClientTests.java @@ -24,6 +24,7 @@ import io.orkes.conductor.client.http.OrkesMetadataClient; import io.orkes.conductor.client.model.TagObject; import io.orkes.conductor.client.util.Commons; +import io.orkes.conductor.client.util.TestUtil; import io.orkes.conductor.client.util.WorkflowUtil; import static org.junit.jupiter.api.Assertions.*; @@ -33,6 +34,7 @@ public class MetadataClientTests extends ClientTest { public MetadataClientTests() { metadataClient = super.orkesClients.getMetadataClient(); + ((OrkesMetadataClient) metadataClient).withReadTimeout(45000); } @Test @@ -68,14 +70,14 @@ void workflow() { metadataClient.registerWorkflowDef(workflowDef, true); ((OrkesMetadataClient) metadataClient) .getWorkflowDefWithMetadata(Commons.WORKFLOW_NAME, Commons.WORKFLOW_VERSION); - WorkflowDef receivedWorkflowDef = - metadataClient.getWorkflowDef(Commons.WORKFLOW_NAME, Commons.WORKFLOW_VERSION); + WorkflowDef receivedWorkflowDef = metadataClient.getWorkflowDef(Commons.WORKFLOW_NAME, + Commons.WORKFLOW_VERSION); assertTrue(receivedWorkflowDef.getName().equals(Commons.WORKFLOW_NAME)); assertEquals(receivedWorkflowDef.getVersion(), Commons.WORKFLOW_VERSION); } @Test - void tagTask() { + void tagTask() throws Exception { metadataClient.registerTaskDefs(List.of(Commons.getTaskDef())); try { metadataClient.deleteTaskTag(Commons.getTagString(), Commons.TASK_NAME); @@ -87,10 +89,15 @@ void tagTask() { TagObject tagObject = Commons.getTagObject(); metadataClient.addTaskTag(tagObject, Commons.TASK_NAME); metadataClient.setTaskTags(List.of(tagObject), Commons.TASK_NAME); - List tags = metadataClient.getTaskTags(Commons.TASK_NAME); + assertNotNull( + TestUtil.retryMethodCall( + () -> metadataClient.getTags())); + List tags = (List) TestUtil.retryMethodCall( + () -> metadataClient.getTaskTags(Commons.TASK_NAME)); assertIterableEquals(List.of(tagObject), tags); metadataClient.deleteTaskTag(Commons.getTagString(), Commons.TASK_NAME); - tags = metadataClient.getTaskTags(Commons.TASK_NAME); + tags = (List) TestUtil.retryMethodCall( + () -> metadataClient.getTaskTags(Commons.TASK_NAME)); assertIterableEquals(List.of(), tags); } diff --git a/src/test/java/io/orkes/conductor/client/api/SecretClientTests.java b/src/test/java/io/orkes/conductor/client/api/SecretClientTests.java index faf6ecce..696d7b3e 100644 --- a/src/test/java/io/orkes/conductor/client/api/SecretClientTests.java +++ b/src/test/java/io/orkes/conductor/client/api/SecretClientTests.java @@ -12,10 +12,13 @@ */ package io.orkes.conductor.client.api; +import java.util.List; + import org.junit.jupiter.api.Test; import io.orkes.conductor.client.SecretClient; import io.orkes.conductor.client.http.ApiException; +import io.orkes.conductor.client.model.TagObject; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -40,10 +43,19 @@ void testMethods() { } } secretClient.putSecret(SECRET_NAME, SECRET_KEY); + secretClient.putTagForSecret(List.of(getTagObject()), SECRET_KEY); assertTrue(secretClient.listSecretsThatUserCanGrantAccessTo().contains(SECRET_KEY)); assertTrue(secretClient.listAllSecretNames().contains(SECRET_KEY)); assertEquals(SECRET_NAME, secretClient.getSecret(SECRET_KEY)); assertTrue(secretClient.secretExists(SECRET_KEY)); secretClient.deleteSecret(SECRET_KEY); } + + private TagObject getTagObject() { + TagObject tagObject = new TagObject(); + tagObject.setType(TagObject.TypeEnum.METADATA); + tagObject.setKey("department"); + tagObject.setValue("accounts"); + return tagObject; + } } diff --git a/src/test/java/io/orkes/conductor/client/api/TaskClientTests.java b/src/test/java/io/orkes/conductor/client/api/TaskClientTests.java new file mode 100644 index 00000000..a1b91f98 --- /dev/null +++ b/src/test/java/io/orkes/conductor/client/api/TaskClientTests.java @@ -0,0 +1,276 @@ +/* + * Copyright 2023 Orkes, Inc. + *

+ * Licensed 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 io.orkes.conductor.client.api; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.testcontainers.shaded.com.google.common.util.concurrent.Uninterruptibles; + +import com.netflix.conductor.common.config.ObjectMapperProvider; +import com.netflix.conductor.common.metadata.tasks.Task; +import com.netflix.conductor.common.metadata.tasks.TaskDef; +import com.netflix.conductor.common.metadata.tasks.TaskExecLog; +import com.netflix.conductor.common.metadata.tasks.TaskResult; +import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest; +import com.netflix.conductor.common.metadata.workflow.WorkflowDef; +import com.netflix.conductor.common.run.Workflow; +import com.netflix.conductor.sdk.workflow.def.ConductorWorkflow; +import com.netflix.conductor.sdk.workflow.def.tasks.SimpleTask; +import com.netflix.conductor.sdk.workflow.executor.WorkflowExecutor; + +import io.orkes.conductor.client.MetadataClient; +import io.orkes.conductor.client.TaskClient; +import io.orkes.conductor.client.WorkflowClient; +import io.orkes.conductor.client.http.ApiException; +import io.orkes.conductor.client.util.TestUtil; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import static org.junit.jupiter.api.Assertions.*; + +public class TaskClientTests extends ClientTest { + + private static TaskClient taskClient; + private static WorkflowClient workflowClient; + private static MetadataClient metadataClient; + private static WorkflowExecutor workflowExecutor; + + private static String workflowName = ""; + + @BeforeAll + public static void setup() throws IOException { + taskClient = orkesClients.getTaskClient(); + metadataClient = orkesClients.getMetadataClient(); + workflowClient = orkesClients.getWorkflowClient(); + InputStream is = TaskClientTests.class.getResourceAsStream("/sdk_test.json"); + ObjectMapper om = new ObjectMapperProvider().getObjectMapper(); + WorkflowDef workflowDef = om.readValue(new InputStreamReader(is), WorkflowDef.class); + metadataClient.registerWorkflowDef(workflowDef, true); + workflowName = workflowDef.getName(); + workflowExecutor = new WorkflowExecutor( + orkesClients.getTaskClient(), + orkesClients.getWorkflowClient(), + orkesClients.getMetadataClient(), + 10); + } + + @Test + public void testUpdateByRefName() { + StartWorkflowRequest request = new StartWorkflowRequest(); + request.setName(workflowName); + request.setVersion(1); + request.setInput(new HashMap<>()); + String workflowId = workflowClient.startWorkflow(request); + System.out.println(workflowId); + Workflow workflow = workflowClient.getWorkflow(workflowId, true); + assertNotNull(workflow); + + int maxLoop = 10; + int count = 0; + while (!workflow.getStatus().isTerminal() && count < maxLoop) { + workflow.getTasks().stream().filter(t -> !t.getStatus().isTerminal()).forEach(running -> { + String referenceName = running.getReferenceTaskName(); + System.out.println("Updating " + referenceName); + taskClient.updateTask(workflowId, referenceName, TaskResult.Status.COMPLETED, Map.of("k", "value")); + }); + count++; + Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); + workflow = workflowClient.getWorkflow(workflowId, true); + } + assertTrue(count < maxLoop); + workflow = workflowClient.getWorkflow(workflowId, true); + assertEquals(Workflow.WorkflowStatus.COMPLETED, workflow.getStatus()); + } + + @Test + public void testUpdateByRefNameSync() { + StartWorkflowRequest request = new StartWorkflowRequest(); + request.setName(workflowName); + request.setVersion(1); + request.setInput(new HashMap<>()); + String workflowId = workflowClient.startWorkflow(request); + System.out.println(workflowId); + Workflow workflow = workflowClient.getWorkflow(workflowId, true); + assertNotNull(workflow); + + int maxLoop = 10; + int count = 0; + while (!workflow.getStatus().isTerminal() && count < maxLoop) { + workflow = workflowClient.getWorkflow(workflowId, true); + List runningTasks = workflow.getTasks().stream() + .filter(task -> !task.getStatus().isTerminal() && task.getTaskType().equals("there_is_no_worker")) + .map(t -> t.getReferenceTaskName()) + .collect(Collectors.toList()); + System.out.println("Running tasks: " + runningTasks); + if (runningTasks.isEmpty()) { + Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); + count++; + continue; + } + for (String referenceName : runningTasks) { + System.out.println("Updating " + referenceName); + try { + workflow = taskClient.updateTaskSync(workflowId, referenceName, TaskResult.Status.COMPLETED, + new TaskOutput()); + System.out.println("Workflow: " + workflow); + } catch (ApiException apiException) { + // 404 == task was updated already and there are no pending tasks + if (apiException.getStatusCode() != 404) { + fail(apiException); + } + } + } + count++; + } + assertTrue(count < maxLoop); + workflow = workflowClient.getWorkflow(workflowId, true); + assertEquals(Workflow.WorkflowStatus.COMPLETED, workflow.getStatus()); + } + + @Test + public void testTaskLog() throws Exception { + var workflowName = "random_workflow_name_1hqiuwhjasdsadqqwe"; + var taskName1 = "random_task_name_1najsbdha"; + var taskName2 = "random_task_name_1bhasvdgasvd12y378t"; + + var taskDef1 = new TaskDef(taskName1); + taskDef1.setRetryCount(0); + taskDef1.setOwnerEmail("test@orkes.io"); + var taskDef2 = new TaskDef(taskName2); + taskDef2.setRetryCount(0); + taskDef2.setOwnerEmail("test@orkes.io"); + + TestUtil.retryMethodCall( + () -> metadataClient.registerTaskDefs(List.of(taskDef1, taskDef2))); + + var wf = new ConductorWorkflow<>(workflowExecutor); + wf.setName(workflowName); + wf.setVersion(1); + wf.add(new SimpleTask(taskName1, taskName1)); + wf.add(new SimpleTask(taskName2, taskName2)); + TestUtil.retryMethodCall( + () -> wf.registerWorkflow(true)); + + StartWorkflowRequest startWorkflowRequest = new StartWorkflowRequest(); + startWorkflowRequest.setName(workflowName); + startWorkflowRequest.setVersion(1); + startWorkflowRequest.setInput(new HashMap<>()); + var workflowId = (String) TestUtil.retryMethodCall( + () -> workflowClient.startWorkflow(startWorkflowRequest)); + System.out.println("Started workflow with id: " + workflowId); + + var task = (Task) TestUtil.retryMethodCall( + () -> taskClient.pollTask(taskName1, "random worker", null)); + assertNotNull(task); + var taskId = task.getTaskId(); + + TestUtil.retryMethodCall( + () -> taskClient.logMessageForTask(taskId, "random message")); + var logs = (List) TestUtil.retryMethodCall( + () -> taskClient.getTaskLogs(taskId)); + assertNotNull(logs); + var details = (Task) TestUtil.retryMethodCall( + () -> taskClient.getTaskDetails(taskId)); + assertNotNull(details); + TestUtil.retryMethodCall( + () -> taskClient.requeuePendingTasksByTaskType(taskName2)); + TestUtil.retryMethodCall( + () -> taskClient.getQueueSizeForTask(taskName1)); + TestUtil.retryMethodCall( + () -> taskClient.getQueueSizeForTask(taskName1, null, null, null)); + TestUtil.retryMethodCall( + () -> taskClient.batchPollTasksByTaskType(taskName2, "random worker id", 5, 3000)); + } + + @Test + public void testUnsupportedMethods() { + assertThrows( + UnsupportedOperationException.class, + () -> { + taskClient.ack("taskName", "workerId"); + }); + assertThrows( + UnsupportedOperationException.class, + () -> { + taskClient.removeTaskFromQueue("taskName", "taskId"); + }); + assertThrows( + UnsupportedOperationException.class, + () -> { + taskClient.getPollData("taskName"); + }); + assertThrows( + UnsupportedOperationException.class, + () -> { + taskClient.getAllPollData(); + }); + assertThrows( + UnsupportedOperationException.class, + () -> { + taskClient.requeueAllPendingTasks(); + }); + assertThrows( + UnsupportedOperationException.class, + () -> { + taskClient.search("freeText"); + }); + assertThrows( + UnsupportedOperationException.class, + () -> { + taskClient.searchV2("freeText"); + }); + assertThrows( + UnsupportedOperationException.class, + () -> { + taskClient.search(4, 20, "sort", "freeText", "query"); + }); + + assertThrows( + UnsupportedOperationException.class, + () -> { + taskClient.searchV2(4, 20, "sort", "freeText", "query"); + }); + } + + private static class TaskOutput { + private String name = "hello"; + + private BigDecimal value = BigDecimal.TEN; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public BigDecimal getValue() { + return value; + } + + public void setValue(BigDecimal value) { + this.value = value; + } + } +} diff --git a/src/test/java/io/orkes/conductor/client/api/TaskUpdateTests.java b/src/test/java/io/orkes/conductor/client/api/TaskUpdateTests.java deleted file mode 100644 index 86c92c98..00000000 --- a/src/test/java/io/orkes/conductor/client/api/TaskUpdateTests.java +++ /dev/null @@ -1,150 +0,0 @@ -package io.orkes.conductor.client.api; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.netflix.conductor.common.config.ObjectMapperProvider; -import com.netflix.conductor.common.metadata.tasks.Task; -import com.netflix.conductor.common.metadata.tasks.TaskResult; -import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest; -import com.netflix.conductor.common.metadata.workflow.WorkflowDef; -import com.netflix.conductor.common.run.Workflow; -import io.orkes.conductor.client.MetadataClient; -import io.orkes.conductor.client.OrkesClients; -import io.orkes.conductor.client.TaskClient; -import io.orkes.conductor.client.WorkflowClient; -import io.orkes.conductor.client.http.ApiException; -import io.orkes.conductor.client.http.OrkesTaskClient; -import io.orkes.conductor.client.util.ApiUtil; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.testcontainers.shaded.com.google.common.util.concurrent.Uninterruptibles; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.math.BigDecimal; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import static org.junit.jupiter.api.Assertions.*; - -public class TaskUpdateTests { - - private static TaskClient taskClient; - - private static WorkflowClient workflowClient; - - private static MetadataClient metadataClient; - - private static String workflowName = ""; - - private static List tasks = null; - - @BeforeAll - public static void setup() throws IOException { - OrkesClients orkesClients = ApiUtil.getOrkesClient(); - taskClient = orkesClients.getTaskClient(); - metadataClient = orkesClients.getMetadataClient(); - workflowClient = orkesClients.getWorkflowClient(); - InputStream is = TaskUpdateTests.class.getResourceAsStream("/sdk_test.json"); - ObjectMapper om = new ObjectMapperProvider().getObjectMapper(); - WorkflowDef workflowDef = om.readValue(new InputStreamReader(is), WorkflowDef.class); - metadataClient.registerWorkflowDef(workflowDef, true); - workflowName = workflowDef.getName(); - tasks = workflowDef.collectTasks().stream().map(task -> task.getTaskReferenceName()).collect(Collectors.toList()); - } - @Test - public void testUpdateByRefName() { - StartWorkflowRequest request = new StartWorkflowRequest(); - request.setName(workflowName); - request.setVersion(1); - request.setInput(new HashMap<>()); - String workflowId = workflowClient.startWorkflow(request); - System.out.println(workflowId); - Workflow workflow = workflowClient.getWorkflow(workflowId, true); - assertNotNull(workflow); - - int maxLoop = 10; - int count = 0; - while (!workflow.getStatus().isTerminal() && count < maxLoop) { - workflow.getTasks().stream().filter(t -> !t.getStatus().isTerminal()).forEach(running -> { - String referenceName = running.getReferenceTaskName(); - System.out.println("Updating " + referenceName); - taskClient.updateTask(workflowId, referenceName, TaskResult.Status.COMPLETED, Map.of("k", "value")); - }); - count++; - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflow = workflowClient.getWorkflow(workflowId, true); - } - assertTrue(count < maxLoop); - workflow = workflowClient.getWorkflow(workflowId, true); - assertEquals(Workflow.WorkflowStatus.COMPLETED, workflow.getStatus()); - } - - @Test - public void testUpdateByRefNameSync() { - StartWorkflowRequest request = new StartWorkflowRequest(); - request.setName(workflowName); - request.setVersion(1); - request.setInput(new HashMap<>()); - String workflowId = workflowClient.startWorkflow(request); - System.out.println(workflowId); - Workflow workflow = workflowClient.getWorkflow(workflowId, true); - assertNotNull(workflow); - - int maxLoop = 10; - int count = 0; - while (!workflow.getStatus().isTerminal() && count < maxLoop) { - List runningTasks = workflow.getTasks().stream() - .filter(task -> !task.getStatus().isTerminal() && task.getTaskType().equals("there_is_no_worker")) - .map(t -> t.getReferenceTaskName()) - .collect(Collectors.toList()); - System.out.println("Running tasks: " + runningTasks); - if(runningTasks.isEmpty()) { - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - count++; - continue; - } - for (String referenceName : runningTasks) { - System.out.println("Updating " + referenceName); - try { - workflow = taskClient.updateTaskSync(workflowId, referenceName, TaskResult.Status.COMPLETED, new TaskOutput()); - System.out.println("Workflow: " + workflow); - } catch (ApiException apiException) { - //404 == task was updated already and there are no pending tasks - if(apiException.getStatusCode() != 404) { - fail(apiException); - } - } - } - count++; - } - assertTrue(count < maxLoop); - workflow = workflowClient.getWorkflow(workflowId, true); - assertEquals(Workflow.WorkflowStatus.COMPLETED, workflow.getStatus()); - } - - private static class TaskOutput { - private String name = "hello"; - - private BigDecimal value = BigDecimal.TEN; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public BigDecimal getValue() { - return value; - } - - public void setValue(BigDecimal value) { - this.value = value; - } - } -} diff --git a/src/test/java/io/orkes/conductor/client/api/WorkflowClientTests.java b/src/test/java/io/orkes/conductor/client/api/WorkflowClientTests.java index ca04e358..18c402e8 100644 --- a/src/test/java/io/orkes/conductor/client/api/WorkflowClientTests.java +++ b/src/test/java/io/orkes/conductor/client/api/WorkflowClientTests.java @@ -16,36 +16,42 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import com.netflix.conductor.common.metadata.workflow.WorkflowDef; -import com.netflix.conductor.sdk.workflow.def.tasks.SimpleTask; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import com.netflix.conductor.common.metadata.tasks.TaskDef; import com.netflix.conductor.common.metadata.workflow.RerunWorkflowRequest; import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest; +import com.netflix.conductor.common.metadata.workflow.WorkflowDef; import com.netflix.conductor.common.run.Workflow; import com.netflix.conductor.sdk.workflow.def.ConductorWorkflow; import com.netflix.conductor.sdk.workflow.def.tasks.Http; +import com.netflix.conductor.sdk.workflow.def.tasks.SimpleTask; import com.netflix.conductor.sdk.workflow.executor.WorkflowExecutor; +import io.orkes.conductor.client.MetadataClient; import io.orkes.conductor.client.WorkflowClient; import io.orkes.conductor.client.http.ApiException; import io.orkes.conductor.client.util.Commons; +import io.orkes.conductor.client.util.TestUtil; import com.google.common.util.concurrent.Uninterruptibles; import static org.junit.jupiter.api.Assertions.*; public class WorkflowClientTests extends ClientTest { - private final WorkflowClient workflowClient; - - private final WorkflowExecutor workflowExecutor; + private static WorkflowClient workflowClient; + private static MetadataClient metadataClient; + private static WorkflowExecutor workflowExecutor; - public WorkflowClientTests() { - this.workflowClient = super.orkesClients.getWorkflowClient(); - this.workflowExecutor = new WorkflowExecutor( - super.orkesClients.getTaskClient(), - super.orkesClients.getWorkflowClient(), - super.orkesClients.getMetadataClient(), + @BeforeAll + public static void setup() { + workflowClient = orkesClients.getWorkflowClient(); + metadataClient = orkesClients.getMetadataClient(); + workflowExecutor = new WorkflowExecutor( + orkesClients.getTaskClient(), + orkesClients.getWorkflowClient(), + orkesClients.getMetadataClient(), 10); } @@ -80,70 +86,78 @@ public void testSearchByCorrelationIds() { correlationIdToWorkflows.put(correlationId, ids); } } - //Let's give couple of seconds for indexing to complete + // Let's give couple of seconds for indexing to complete Uninterruptibles.sleepUninterruptibly(2, TimeUnit.SECONDS); - Map> result = workflowClient.getWorkflowsByNamesAndCorrelationIds(correlationIds, workflowNames.stream().collect(Collectors.toList()), true, false); + Map> result = workflowClient.getWorkflowsByNamesAndCorrelationIds(correlationIds, + workflowNames.stream().collect(Collectors.toList()), true, false); assertNotNull(result); assertEquals(correlationIds.size(), result.size()); for (String correlationId : correlationIds) { assertEquals(5, result.get(correlationId).size()); - Set ids = result.get(correlationId).stream().map(wf -> wf.getWorkflowId()).collect(Collectors.toSet()); + Set ids = result.get(correlationId).stream().map(wf -> wf.getWorkflowId()) + .collect(Collectors.toSet()); assertEquals(correlationIdToWorkflows.get(correlationId), ids); } } @Test - public void testWorkflowMethods() { - String workflowId = workflowClient.startWorkflow(getStartWorkflowRequest()); - List workflows = - workflowClient.getWorkflows( - Commons.WORKFLOW_NAME, "askdjbjqhbdjqhbdjqhsbdjqhsbd", false, false); + public void testWorkflowMethods() throws Exception { + var workflowId = workflowClient.startWorkflow(getStartWorkflowRequest()); + var workflows = (List) TestUtil.retryMethodCall( + () -> workflowClient.getWorkflows( + Commons.WORKFLOW_NAME, "askdjbjqhbdjqhbdjqhsbdjqhsbd", false, false)); assertTrue(workflows.isEmpty()); - workflowClient.terminateWorkflow(workflowId, "reason"); - workflowClient.retryLastFailedTask(workflowId); - workflowClient.getRunningWorkflow(Commons.WORKFLOW_NAME, Commons.WORKFLOW_VERSION); - workflowClient.getWorkflowsByTimePeriod( - Commons.WORKFLOW_NAME, Commons.WORKFLOW_VERSION, 0L, 0L); - workflowClient.search(2, 5, "", "", Commons.WORKFLOW_NAME); - workflowClient.terminateWorkflows(List.of(workflowId), "reason"); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.restart(workflowId, true); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.terminateWorkflow(List.of(workflowId), "reason"); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.restartWorkflow(List.of(workflowId), true); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.terminateWorkflow(workflowId, "reason"); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.retryWorkflow(List.of(workflowId)); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.terminateWorkflow(workflowId, "reason"); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.rerunWorkflow(workflowId, new RerunWorkflowRequest()); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.pauseWorkflow(workflowId); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.resumeWorkflow(workflowId); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.pauseWorkflow(workflowId); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); + TestUtil.retryMethodCall( + () -> workflowClient.terminateWorkflow(workflowId, "reason")); + TestUtil.retryMethodCall( + () -> workflowClient.retryLastFailedTask(workflowId)); + TestUtil.retryMethodCall( + () -> workflowClient.getRunningWorkflow(Commons.WORKFLOW_NAME, Commons.WORKFLOW_VERSION)); + TestUtil.retryMethodCall( + () -> workflowClient.getWorkflowsByTimePeriod( + Commons.WORKFLOW_NAME, Commons.WORKFLOW_VERSION, 0L, 0L)); + TestUtil.retryMethodCall( + () -> workflowClient.search(2, 5, "", "", Commons.WORKFLOW_NAME)); + TestUtil.retryMethodCall( + () -> workflowClient.terminateWorkflows(List.of(workflowId), "reason")); + TestUtil.retryMethodCall( + () -> workflowClient.restart(workflowId, true)); try { - workflowClient.skipTaskFromWorkflow(workflowId, Commons.TASK_NAME); + TestUtil.retryMethodCall( + () -> workflowClient.skipTaskFromWorkflow(workflowId, Commons.TASK_NAME)); } catch (ApiException e) { - if (e.getStatusCode() != 500) { - throw e; - } + assertEquals(e.getCode(), "500"); } - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.pauseWorkflow(List.of(workflowId)); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.resumeWorkflow(List.of(workflowId)); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.deleteWorkflow(workflowId, false); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.search(Commons.WORKFLOW_NAME); - Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); - workflowClient.runDecider(workflowId); + TestUtil.retryMethodCall( + () -> workflowClient.terminateWorkflow(List.of(workflowId), "reason")); + TestUtil.retryMethodCall( + () -> workflowClient.restartWorkflow(List.of(workflowId), true)); + TestUtil.retryMethodCall( + () -> workflowClient.terminateWorkflow(workflowId, "reason")); + TestUtil.retryMethodCall( + () -> workflowClient.retryWorkflow(List.of(workflowId))); + TestUtil.retryMethodCall( + () -> workflowClient.terminateWorkflow(workflowId, "reason")); + TestUtil.retryMethodCall( + () -> workflowClient.rerunWorkflow(workflowId, new RerunWorkflowRequest())); + TestUtil.retryMethodCall( + () -> workflowClient.pauseWorkflow(workflowId)); + TestUtil.retryMethodCall( + () -> workflowClient.resumeWorkflow(workflowId)); + TestUtil.retryMethodCall( + () -> workflowClient.pauseWorkflow(workflowId)); + TestUtil.retryMethodCall( + () -> workflowClient.resumeWorkflow(workflowId)); + TestUtil.retryMethodCall( + () -> workflowClient.pauseWorkflow(List.of(workflowId))); + TestUtil.retryMethodCall( + () -> workflowClient.resumeWorkflow(List.of(workflowId))); + TestUtil.retryMethodCall( + () -> workflowClient.deleteWorkflow(workflowId, false)); + TestUtil.retryMethodCall( + () -> workflowClient.search(Commons.WORKFLOW_NAME)); + TestUtil.retryMethodCall( + () -> workflowClient.runDecider(workflowId)); } @Test @@ -155,9 +169,47 @@ public void testWorkflowTerminate() { assertEquals(Workflow.WorkflowStatus.TERMINATED, workflow.getStatus()); } + @Test + public void testSkipTaskFromWorkflow() throws Exception { + var workflowName = "random_workflow_name_1hqiuwheiquwhe"; + var taskName1 = "random_task_name_1hqiuwheiquwheajnsdsand"; + var taskName2 = "random_task_name_1hqiuwheiquwheajnsdsandjsadh"; + + var taskDef1 = new TaskDef(taskName1); + taskDef1.setRetryCount(0); + taskDef1.setOwnerEmail("test@orkes.io"); + var taskDef2 = new TaskDef(taskName2); + taskDef2.setRetryCount(0); + taskDef2.setOwnerEmail("test@orkes.io"); + + TestUtil.retryMethodCall( + () -> metadataClient.registerTaskDefs(List.of(taskDef1, taskDef2))); + + var wf = new ConductorWorkflow<>(workflowExecutor); + wf.setName(workflowName); + wf.setVersion(1); + wf.add(new SimpleTask(taskName1, taskName1)); + wf.add(new SimpleTask(taskName2, taskName2)); + TestUtil.retryMethodCall( + () -> wf.registerWorkflow(true)); + + StartWorkflowRequest startWorkflowRequest = new StartWorkflowRequest(); + startWorkflowRequest.setName(workflowName); + startWorkflowRequest.setVersion(1); + startWorkflowRequest.setInput(new HashMap<>()); + var workflowId = (String) TestUtil.retryMethodCall( + () -> workflowClient.startWorkflow(startWorkflowRequest)); + System.out.println("workflowId: " + workflowId); + + TestUtil.retryMethodCall( + () -> workflowClient.skipTaskFromWorkflow(workflowId, taskName2)); + TestUtil.retryMethodCall( + () -> workflowClient.terminateWorkflowsWithFailure(List.of(workflowId), null, false)); + } + public void testUpdateVariables() { ConductorWorkflow workflow = new ConductorWorkflow<>(workflowExecutor); - workflow.add(new SimpleTask("simple_task","simple_task_ref")); + workflow.add(new SimpleTask("simple_task", "simple_task_ref")); workflow.setTimeoutPolicy(WorkflowDef.TimeoutPolicy.TIME_OUT_WF); workflow.setTimeoutSeconds(60); workflow.setName("update_variable_test"); @@ -214,6 +266,11 @@ void testUnsupportedMethods() { }); } + @Test + void testExecuteWorkflow() { + // TODO + } + StartWorkflowRequest getStartWorkflowRequest() { StartWorkflowRequest startWorkflowRequest = new StartWorkflowRequest(); startWorkflowRequest.setName(Commons.WORKFLOW_NAME); diff --git a/src/test/java/io/orkes/conductor/client/sdk/WorkflowSDKTests.java b/src/test/java/io/orkes/conductor/client/sdk/WorkflowSDKTests.java new file mode 100644 index 00000000..13a820ad --- /dev/null +++ b/src/test/java/io/orkes/conductor/client/sdk/WorkflowSDKTests.java @@ -0,0 +1,83 @@ +/* + * Copyright 2023 Orkes, Inc. + *

+ * Licensed 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 io.orkes.conductor.client.sdk; + +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.junit.jupiter.api.Test; + +import com.netflix.conductor.common.run.Workflow; +import com.netflix.conductor.sdk.workflow.def.ConductorWorkflow; +import com.netflix.conductor.sdk.workflow.def.tasks.SimpleTask; +import com.netflix.conductor.sdk.workflow.executor.WorkflowExecutor; +import com.netflix.conductor.sdk.workflow.executor.task.WorkerConfiguration; +import com.netflix.conductor.sdk.workflow.task.InputParam; +import com.netflix.conductor.sdk.workflow.task.WorkerTask; + +import io.orkes.conductor.client.ApiClient; +import io.orkes.conductor.client.OrkesClients; +import io.orkes.conductor.client.spring.OrkesAnnotatedWorkerExecutor; +import io.orkes.conductor.client.util.ApiUtil; + +import static org.junit.jupiter.api.Assertions.*; + +public class WorkflowSDKTests { + + + @Test + public void testCreateWorkflow() { + ApiClient apiClient = ApiUtil.getApiClientWithCredentials(); + OrkesClients clients = new OrkesClients(apiClient); + OrkesAnnotatedWorkerExecutor workerExecutor = new OrkesAnnotatedWorkerExecutor(clients.getTaskClient(), new WorkerConfiguration()); + workerExecutor.initWorkers("io.orkes.conductor.client.sdk"); + workerExecutor.startPolling(); + + WorkflowExecutor executor = new WorkflowExecutor( + clients.getTaskClient(), + clients.getWorkflowClient(), + clients.getMetadataClient(), + workerExecutor); + + ConductorWorkflow workflow = new ConductorWorkflow<>(executor); + workflow.setName("sdk_workflow"); + workflow.setVersion(1); + workflow.add(new SimpleTask("sdk_task", "sdk_task")); + + workflow.registerWorkflow(true, true); + + CompletableFuture result = workflow.execute(Map.of("name", "orkes")); + assertNotNull(result); + try { + + Workflow executedWorkflow = result.get(1, TimeUnit.SECONDS); + assertNotNull(executedWorkflow); + assertEquals(Workflow.WorkflowStatus.COMPLETED, executedWorkflow.getStatus()); + + } catch (InterruptedException e) { + fail(e.getMessage()); + } catch (ExecutionException e) { + fail(e.getMessage()); + } catch (TimeoutException e) { + fail(e.getMessage()); + } + } + + @WorkerTask(value = "sdk_task", pollingInterval = 10) + public String sdkTask(@InputParam("name") String name) { + return "Hello " + name; + } +} diff --git a/src/test/java/io/orkes/conductor/client/spring/ExampleClient.java b/src/test/java/io/orkes/conductor/client/spring/ExampleClient.java new file mode 100644 index 00000000..50e9188a --- /dev/null +++ b/src/test/java/io/orkes/conductor/client/spring/ExampleClient.java @@ -0,0 +1,84 @@ +/* + * Copyright 2020 Orkes, Inc. + *

+ * Licensed 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 io.orkes.conductor.client.spring; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +import com.netflix.conductor.client.worker.Worker; +import com.netflix.conductor.common.metadata.tasks.Task; +import com.netflix.conductor.common.metadata.tasks.TaskResult; +import com.netflix.conductor.sdk.workflow.executor.task.WorkerConfiguration; + +import io.orkes.conductor.client.TaskClient; +import io.orkes.conductor.client.automator.TaskRunnerConfigurer; + +import lombok.extern.slf4j.Slf4j; + +@SpringBootApplication +@Slf4j +public class ExampleClient { + + public static void main(String[] args) { + SpringApplication.run(ExampleClient.class, args); + } + + @Bean + public TaskRunnerConfigurer taskRunnerConfigurer(TaskClient taskClient, List workers, + WorkerConfiguration configuration) { + Map taskToDomain = new HashMap<>(); + Map taskToThreads = new HashMap<>(); + for (Worker worker : workers) { + String taskType = worker.getTaskDefName(); + String domain = configuration.getDomain(taskType); + if(StringUtils.isNotBlank(domain)) { + taskToDomain.put(taskType, domain); + } + int threadCount = configuration.getThreadCount(taskType); + if(threadCount > 0) { + taskToThreads.put(taskType, threadCount); + } + } + TaskRunnerConfigurer trc = new TaskRunnerConfigurer.Builder(taskClient, workers) + .withThreadCount(1) + .withTaskThreadCount(taskToThreads) + .withTaskToDomain(taskToDomain) + .build(); + trc.init(); + return trc; + } + + @Bean + public Worker worker() { + return new Worker() { + @Override + public String getTaskDefName() { + return "xyz"; + } + + @Override + public TaskResult execute(Task task) { + log.info("Execute..."); + TaskResult result = new TaskResult(task); + result.setStatus(TaskResult.Status.COMPLETED); + return result; + } + }; + } +} diff --git a/src/test/java/io/orkes/conductor/client/spring/Workers.java b/src/test/java/io/orkes/conductor/client/spring/Workers.java new file mode 100644 index 00000000..be4902ab --- /dev/null +++ b/src/test/java/io/orkes/conductor/client/spring/Workers.java @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Orkes, Inc. + *

+ * Licensed 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 io.orkes.conductor.client.spring; + +import java.util.Date; + +import org.springframework.stereotype.Component; + +import com.netflix.conductor.sdk.workflow.executor.task.TaskContext; +import com.netflix.conductor.sdk.workflow.task.InputParam; +import com.netflix.conductor.sdk.workflow.task.WorkerTask; + +@Component +public class Workers { + + @WorkerTask(value = "hello", threadCount = 3) + public String helloWorld(@InputParam("name") String name) { + TaskContext context = TaskContext.get(); + System.out.println(new Date() + ":: Poll count: " + context.getPollCount()); + if (context.getPollCount() < 5) { + context.addLog("Not ready yet, poll count is only " + context.getPollCount()); + context.setCallbackAfter(1); + } + + return "Hello, " + name; + } + + @WorkerTask(value = "hello_again", pollingInterval = 333) + public String helloAgain(@InputParam("name") String name) { + TaskContext context = TaskContext.get(); + System.out.println(new Date() + ":: Poll count: " + context.getPollCount()); + if (context.getPollCount() < 5) { + context.addLog("Not ready yet, poll count is only " + context.getPollCount()); + context.setCallbackAfter(1); + } + + return "Hello (again), " + name; + } +} diff --git a/src/test/java/io/orkes/conductor/client/util/TestUtil.java b/src/test/java/io/orkes/conductor/client/util/TestUtil.java new file mode 100644 index 00000000..22104e77 --- /dev/null +++ b/src/test/java/io/orkes/conductor/client/util/TestUtil.java @@ -0,0 +1,66 @@ +/* + * Copyright 2023 Orkes, Inc. + *

+ * Licensed 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 io.orkes.conductor.client.util; + +public class TestUtil { + private static int RETRY_ATTEMPT_LIMIT = 4; + + public static void retryMethodCall(VoidRunnableWithException function) + throws Exception { + Exception lastException = null; + for (int retryCounter = 0; retryCounter < RETRY_ATTEMPT_LIMIT; retryCounter += 1) { + try { + function.run(); + return; + } catch (Exception e) { + lastException = e; + System.out.println("Attempt " + (retryCounter + 1) + " failed: " + e.getMessage()); + try { + Thread.sleep(1000 * (1 << retryCounter)); // Sleep for 2^retryCounter second(s) before retrying + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + throw lastException; + } + + public static Object retryMethodCall(RunnableWithException function) + throws Exception { + Exception lastException = null; + for (int retryCounter = 0; retryCounter < RETRY_ATTEMPT_LIMIT; retryCounter += 1) { + try { + return function.run(); + } catch (Exception e) { + lastException = e; + System.out.println("Attempt " + (retryCounter + 1) + " failed: " + e.getMessage()); + try { + Thread.sleep(1000 * (1 << retryCounter)); // Sleep for 2^retryCounter second(s) before retrying + } catch (InterruptedException ex) { + ex.printStackTrace(); + } + } + } + throw lastException; + } + + @FunctionalInterface + public interface RunnableWithException { + Object run() throws Exception; + } + + @FunctionalInterface + public interface VoidRunnableWithException { + void run() throws Exception; + } +} diff --git a/src/test/java/io/orkes/conductor/client/worker/WorkflowExecutionTests.java b/src/test/java/io/orkes/conductor/client/worker/WorkflowExecutionTests.java index 75c0d75a..ab9d784e 100644 --- a/src/test/java/io/orkes/conductor/client/worker/WorkflowExecutionTests.java +++ b/src/test/java/io/orkes/conductor/client/worker/WorkflowExecutionTests.java @@ -16,6 +16,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -34,6 +35,8 @@ import io.orkes.conductor.client.util.Commons; import io.orkes.conductor.client.util.SimpleWorker; +import com.google.common.util.concurrent.Uninterruptibles; + import static org.junit.jupiter.api.Assertions.assertEquals; public class WorkflowExecutionTests { @@ -55,10 +58,10 @@ public void init() { @Test @DisplayName("Test workflow completion") public void workflow() throws Exception { - List workflowIds = startWorkflows(10, Commons.WORKFLOW_NAME); + List workflowIds = startWorkflows(2, Commons.WORKFLOW_NAME); workflowIds.add(startWorkflow(Commons.WORKFLOW_NAME)); this.taskRunnerConfigurer.init(); - Thread.sleep(7 * 1000); + Uninterruptibles.sleepUninterruptibly(10, TimeUnit.SECONDS); workflowIds.forEach(workflowId -> validateCompletedWorkflow(workflowId)); this.taskRunnerConfigurer.shutdown(); } diff --git a/src/test/resources/logback-spring.xml b/src/test/resources/logback-spring.xml new file mode 100644 index 00000000..1bd0fcb6 --- /dev/null +++ b/src/test/resources/logback-spring.xml @@ -0,0 +1,18 @@ + + + + + + + %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable + + + + + + + + + + \ No newline at end of file