Ensure Dapr workflows classes and interfaces have proper packages and visibility (#1176)

* Rename orchestrator and activity wrapper

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Move workflow activity to root package

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Move workflow context implementation to runtime

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Rename workflow activity context and add an interface

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Convert workflow abstract class to interface

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Move saga internals to runtime.saga package

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Tiny typo fix

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Adjusting the class names based on feedback

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Revert accidental JavaDocs commits

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Fixing some compilation errors

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
This commit is contained in:
artur-ciocanu 2025-01-05 00:39:42 +02:00 committed by GitHub
parent 69f24075f6
commit 380cda68f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 154 additions and 138 deletions

View File

@ -1,7 +1,7 @@
package io.dapr.spring.boot.autoconfigure.client.workflows;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;

View File

@ -5,7 +5,7 @@ import io.dapr.workflows.WorkflowStub;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;
public class TestWorkflow extends Workflow {
public class TestWorkflow implements Workflow {
@Autowired
private RestTemplate restTemplate;

View File

@ -1,13 +1,12 @@
package io.dapr.spring.workflows.config;
import io.dapr.workflows.Workflow;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowRuntime;
import io.dapr.workflows.runtime.WorkflowRuntimeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;

View File

@ -42,7 +42,7 @@ public class DaprWorkflowExampleTest {
private static final String noTimeoutWorkflow = "DemoWorkflowNoTimeout";
private static final String workflowDefaultId = "demo-workflow-123";
private class DemoWorkflow extends Workflow {
private class DemoWorkflow implements Workflow {
@Override
public WorkflowStub create() {

View File

@ -16,7 +16,7 @@ package io.dapr.examples.workflows.chain;
import io.dapr.workflows.Workflow;
import io.dapr.workflows.WorkflowStub;
public class DemoChainWorkflow extends Workflow {
public class DemoChainWorkflow implements Workflow {
@Override
public WorkflowStub create() {
return ctx -> {

View File

@ -13,8 +13,8 @@ limitations under the License.
package io.dapr.examples.workflows.chain;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -16,7 +16,7 @@ package io.dapr.examples.workflows.childworkflow;
import io.dapr.workflows.Workflow;
import io.dapr.workflows.WorkflowStub;
public class DemoChildWorkflow extends Workflow {
public class DemoChildWorkflow implements Workflow {
@Override
public WorkflowStub create() {
return ctx -> {

View File

@ -16,7 +16,7 @@ package io.dapr.examples.workflows.childworkflow;
import io.dapr.workflows.Workflow;
import io.dapr.workflows.WorkflowStub;
public class DemoWorkflow extends Workflow {
public class DemoWorkflow implements Workflow {
@Override
public WorkflowStub create() {
return ctx -> {

View File

@ -13,8 +13,8 @@ limitations under the License.
package io.dapr.examples.workflows.childworkflow;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -13,8 +13,8 @@ limitations under the License.
package io.dapr.examples.workflows.continueasnew;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -18,7 +18,7 @@ import io.dapr.workflows.WorkflowStub;
import java.time.Duration;
public class DemoContinueAsNewWorkflow extends Workflow {
public class DemoContinueAsNewWorkflow implements Workflow {
/*
Compared with a CRON schedule, this periodic workflow example will never overlap.
For example, a CRON schedule that executes a cleanup every hour will execute it at 1:00, 2:00, 3:00 etc.

View File

@ -13,8 +13,8 @@ limitations under the License.
package io.dapr.examples.workflows.externalevent;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -16,7 +16,7 @@ package io.dapr.examples.workflows.externalevent;
import io.dapr.workflows.Workflow;
import io.dapr.workflows.WorkflowStub;
public class DemoExternalEventWorkflow extends Workflow {
public class DemoExternalEventWorkflow implements Workflow {
@Override
public WorkflowStub create() {
return ctx -> {

View File

@ -13,8 +13,8 @@ limitations under the License.
package io.dapr.examples.workflows.externalevent;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -13,8 +13,8 @@ limitations under the License.
package io.dapr.examples.workflows.faninout;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -20,7 +20,7 @@ import io.dapr.workflows.WorkflowStub;
import java.util.List;
import java.util.stream.Collectors;
public class DemoFanInOutWorkflow extends Workflow {
public class DemoFanInOutWorkflow implements Workflow {
@Override
public WorkflowStub create() {
return ctx -> {

View File

@ -13,8 +13,8 @@ limitations under the License.
package io.dapr.it.testcontainers;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
public class FirstActivity implements WorkflowActivity {

View File

@ -13,8 +13,8 @@ limitations under the License.
package io.dapr.it.testcontainers;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
public class SecondActivity implements WorkflowActivity {

View File

@ -19,7 +19,7 @@ import org.slf4j.Logger;
import java.time.Duration;
public class TestWorkflow extends Workflow {
public class TestWorkflow implements Workflow {
@Override
public WorkflowStub create() {

View File

@ -21,16 +21,13 @@ import io.dapr.workflows.saga.SagaOption;
/**
* Common interface for workflow implementations.
*/
public abstract class Workflow {
public Workflow() {
}
public interface Workflow {
/**
* Executes the workflow logic.
*
* @return A WorkflowStub.
*/
public abstract WorkflowStub create();
WorkflowStub create();
/**
* Executes the workflow logic.
@ -39,7 +36,7 @@ public abstract class Workflow {
* getting information about the current
* workflow instance.
*/
public void run(WorkflowContext ctx) {
default void run(WorkflowContext ctx) {
WorkflowStub stub = this.create();
if (!this.isSagaEnabled()) {
@ -68,7 +65,7 @@ public abstract class Workflow {
}
}
public boolean isSagaEnabled() {
default boolean isSagaEnabled() {
return this.getSagaOption() != null;
}
@ -77,7 +74,7 @@ public abstract class Workflow {
*
* @return saga configuration
*/
public SagaOption getSagaOption() {
default SagaOption getSagaOption() {
// by default, saga is disabled
return null;
}

View File

@ -11,7 +11,7 @@
limitations under the License.
*/
package io.dapr.workflows.runtime;
package io.dapr.workflows;
/**
* Common interface for task activity implementations.

View File

@ -0,0 +1,20 @@
/*
* Copyright 2023 The Dapr Authors
* 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.dapr.workflows;
public interface WorkflowActivityContext {
String getName();
<T> T getInput(Class<T> targetType);
}

View File

@ -14,11 +14,12 @@ limitations under the License.
package io.dapr.workflows.runtime;
import com.microsoft.durabletask.TaskActivityContext;
import io.dapr.workflows.WorkflowActivityContext;
/**
* Wrapper for Durable Task Framework {@link TaskActivityContext}.
*/
public class WorkflowActivityContext implements TaskActivityContext {
class DefaultWorkflowActivityContext implements WorkflowActivityContext {
private final TaskActivityContext innerContext;
/**
@ -27,7 +28,7 @@ public class WorkflowActivityContext implements TaskActivityContext {
* @param context TaskActivityContext
* @throws IllegalArgumentException if context is null
*/
public WorkflowActivityContext(TaskActivityContext context) throws IllegalArgumentException {
public DefaultWorkflowActivityContext(TaskActivityContext context) throws IllegalArgumentException {
if (context == null) {
throw new IllegalArgumentException("Context cannot be null");
}
@ -39,6 +40,7 @@ public class WorkflowActivityContext implements TaskActivityContext {
*
* @return the name of the current activity
*/
@Override
public String getName() {
return this.innerContext.getName();
}
@ -50,6 +52,7 @@ public class WorkflowActivityContext implements TaskActivityContext {
* @param targetType targetType of the input
* @return the input of the current activity
*/
@Override
public <T> T getInput(Class<T> targetType) {
return this.innerContext.getInput(targetType);
}

View File

@ -11,14 +11,15 @@
limitations under the License.
*/
package io.dapr.workflows;
package io.dapr.workflows.runtime;
import com.microsoft.durabletask.CompositeTaskFailedException;
import com.microsoft.durabletask.Task;
import com.microsoft.durabletask.TaskCanceledException;
import com.microsoft.durabletask.TaskOptions;
import com.microsoft.durabletask.TaskOrchestrationContext;
import io.dapr.workflows.saga.DaprSagaContextImpl;
import io.dapr.workflows.WorkflowContext;
import io.dapr.workflows.runtime.saga.DefaultSagaContext;
import io.dapr.workflows.saga.Saga;
import io.dapr.workflows.saga.SagaContext;
import org.slf4j.Logger;
@ -32,7 +33,7 @@ import java.time.Instant;
import java.util.List;
import java.util.UUID;
public class DaprWorkflowContextImpl implements WorkflowContext {
public class DefaultWorkflowContext implements WorkflowContext {
private final TaskOrchestrationContext innerContext;
private final Logger logger;
private final Saga saga;
@ -43,7 +44,7 @@ public class DaprWorkflowContextImpl implements WorkflowContext {
* @param context TaskOrchestrationContext
* @throws IllegalArgumentException if context is null
*/
public DaprWorkflowContextImpl(TaskOrchestrationContext context) throws IllegalArgumentException {
public DefaultWorkflowContext(TaskOrchestrationContext context) throws IllegalArgumentException {
this(context, LoggerFactory.getLogger(WorkflowContext.class));
}
@ -54,11 +55,11 @@ public class DaprWorkflowContextImpl implements WorkflowContext {
* @param logger Logger
* @throws IllegalArgumentException if context or logger is null
*/
public DaprWorkflowContextImpl(TaskOrchestrationContext context, Logger logger) throws IllegalArgumentException {
public DefaultWorkflowContext(TaskOrchestrationContext context, Logger logger) throws IllegalArgumentException {
this(context, logger, null);
}
public DaprWorkflowContextImpl(TaskOrchestrationContext context, Saga saga) throws IllegalArgumentException {
public DefaultWorkflowContext(TaskOrchestrationContext context, Saga saga) throws IllegalArgumentException {
this(context, LoggerFactory.getLogger(WorkflowContext.class), saga);
}
@ -70,7 +71,7 @@ public class DaprWorkflowContextImpl implements WorkflowContext {
* @param saga saga object, if null, saga is disabled
* @throws IllegalArgumentException if context or logger is null
*/
public DaprWorkflowContextImpl(TaskOrchestrationContext context, Logger logger, Saga saga)
public DefaultWorkflowContext(TaskOrchestrationContext context, Logger logger, Saga saga)
throws IllegalArgumentException {
if (context == null) {
throw new IllegalArgumentException("Context cannot be null");
@ -248,6 +249,6 @@ public class DaprWorkflowContextImpl implements WorkflowContext {
throw new UnsupportedOperationException("Saga is not enabled");
}
return new DaprSagaContextImpl(this.saga, this);
return new DefaultSagaContext(this.saga, this);
}
}

View File

@ -15,6 +15,7 @@ package io.dapr.workflows.runtime;
import com.microsoft.durabletask.TaskActivity;
import com.microsoft.durabletask.TaskActivityFactory;
import io.dapr.workflows.WorkflowActivity;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@ -22,16 +23,16 @@ import java.lang.reflect.InvocationTargetException;
/**
* Wrapper for Durable Task Framework task activity factory.
*/
public class ActivityWrapper<T extends WorkflowActivity> implements TaskActivityFactory {
public class WorkflowActivityWrapper<T extends WorkflowActivity> implements TaskActivityFactory {
private final Constructor<T> activityConstructor;
private final String name;
/**
* Constructor for ActivityWrapper.
* Constructor for WorkflowActivityWrapper.
*
* @param clazz Class of the activity to wrap.
*/
public ActivityWrapper(Class<T> clazz) {
public WorkflowActivityWrapper(Class<T> clazz) {
this.name = clazz.getCanonicalName();
try {
this.activityConstructor = clazz.getDeclaredConstructor();
@ -62,7 +63,7 @@ public class ActivityWrapper<T extends WorkflowActivity> implements TaskActivity
);
}
result = activity.run(new WorkflowActivityContext(ctx));
result = activity.run(new DefaultWorkflowActivityContext(ctx));
return result;
};
}

View File

@ -17,6 +17,7 @@ import com.microsoft.durabletask.DurableTaskGrpcWorkerBuilder;
import io.dapr.config.Properties;
import io.dapr.utils.NetworkUtils;
import io.dapr.workflows.Workflow;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.internal.ApiTokenClientInterceptor;
import io.grpc.ClientInterceptor;
import io.grpc.ManagedChannel;
@ -91,7 +92,7 @@ public class WorkflowRuntimeBuilder {
* @return the WorkflowRuntimeBuilder
*/
public <T extends Workflow> WorkflowRuntimeBuilder registerWorkflow(Class<T> clazz) {
this.builder.addOrchestration(new OrchestratorWrapper<>(clazz));
this.builder.addOrchestration(new WorkflowWrapper<>(clazz));
this.workflowSet.add(clazz.getCanonicalName());
this.workflows.add(clazz.getSimpleName());
@ -108,7 +109,7 @@ public class WorkflowRuntimeBuilder {
* @return the WorkflowRuntimeBuilder
*/
public <T extends WorkflowActivity> WorkflowRuntimeBuilder registerActivity(Class<T> clazz) {
this.builder.addActivity(new ActivityWrapper<>(clazz));
this.builder.addActivity(new WorkflowActivityWrapper<>(clazz));
this.activitySet.add(clazz.getCanonicalName());
this.activities.add(clazz.getSimpleName());

View File

@ -15,7 +15,6 @@ package io.dapr.workflows.runtime;
import com.microsoft.durabletask.TaskOrchestration;
import com.microsoft.durabletask.TaskOrchestrationFactory;
import io.dapr.workflows.DaprWorkflowContextImpl;
import io.dapr.workflows.Workflow;
import io.dapr.workflows.saga.Saga;
@ -25,11 +24,11 @@ import java.lang.reflect.InvocationTargetException;
/**
* Wrapper for Durable Task Framework orchestration factory.
*/
class OrchestratorWrapper<T extends Workflow> implements TaskOrchestrationFactory {
class WorkflowWrapper<T extends Workflow> implements TaskOrchestrationFactory {
private final Constructor<T> workflowConstructor;
private final String name;
public OrchestratorWrapper(Class<T> clazz) {
public WorkflowWrapper(Class<T> clazz) {
this.name = clazz.getCanonicalName();
try {
this.workflowConstructor = clazz.getDeclaredConstructor();
@ -59,9 +58,9 @@ class OrchestratorWrapper<T extends Workflow> implements TaskOrchestrationFactor
if (workflow.getSagaOption() != null) {
Saga saga = new Saga(workflow.getSagaOption());
workflow.run(new DaprWorkflowContextImpl(ctx, saga));
workflow.run(new DefaultWorkflowContext(ctx, saga));
} else {
workflow.run(new DaprWorkflowContextImpl(ctx));
workflow.run(new DefaultWorkflowContext(ctx));
}
};

View File

@ -11,14 +11,16 @@
limitations under the License.
*/
package io.dapr.workflows.saga;
package io.dapr.workflows.runtime.saga;
import io.dapr.workflows.WorkflowContext;
import io.dapr.workflows.saga.Saga;
import io.dapr.workflows.saga.SagaContext;
/**
* Dapr Saga Context implementation.
*/
public class DaprSagaContextImpl implements SagaContext {
public class DefaultSagaContext implements SagaContext {
private final Saga saga;
private final WorkflowContext workflowContext;
@ -30,7 +32,7 @@ public class DaprSagaContextImpl implements SagaContext {
* @param workflowContext Workflow context.
* @throws IllegalArgumentException if saga or workflowContext is null.
*/
public DaprSagaContextImpl(Saga saga, WorkflowContext workflowContext) {
public DefaultSagaContext(Saga saga, WorkflowContext workflowContext) {
if (saga == null) {
throw new IllegalArgumentException("Saga should not be null");
}

View File

@ -18,24 +18,24 @@ import com.microsoft.durabletask.TaskOptions;
/**
* Information for a compensation activity.
*/
class CompensatationInformation {
private final String compensatationActivityClassName;
private final Object compensatationActivityInput;
class CompensationInformation {
private final String compensationActivityClassName;
private final Object compensationActivityInput;
private final TaskOptions taskOptions;
/**
* Constructor for a compensation information.
*
* @param compensatationActivityClassName Class name of the activity to do
* compensatation.
* @param compensatationActivityInput Input of the activity to do
* compensatation.
* @param compensationActivityClassName Class name of the activity to do
* compensation.
* @param compensationActivityInput Input of the activity to do
* compensation.
* @param taskOptions task options to set retry strategy
*/
public CompensatationInformation(String compensatationActivityClassName,
Object compensatationActivityInput, TaskOptions taskOptions) {
this.compensatationActivityClassName = compensatationActivityClassName;
this.compensatationActivityInput = compensatationActivityInput;
public CompensationInformation(String compensationActivityClassName,
Object compensationActivityInput, TaskOptions taskOptions) {
this.compensationActivityClassName = compensationActivityClassName;
this.compensationActivityInput = compensationActivityInput;
this.taskOptions = taskOptions;
}
@ -44,8 +44,8 @@ class CompensatationInformation {
*
* @return the class name of the activity.
*/
public String getCompensatationActivityClassName() {
return compensatationActivityClassName;
public String getCompensationActivityClassName() {
return compensationActivityClassName;
}
/**
@ -53,8 +53,8 @@ class CompensatationInformation {
*
* @return the input of the activity.
*/
public Object getCompensatationActivityInput() {
return compensatationActivityInput;
public Object getCompensationActivityInput() {
return compensationActivityInput;
}
/**
@ -65,4 +65,4 @@ class CompensatationInformation {
public TaskOptions getTaskOptions() {
return taskOptions;
}
}
}

View File

@ -24,7 +24,7 @@ import java.util.List;
public final class Saga {
private final SagaOption option;
private final List<CompensatationInformation> compensationActivities = new ArrayList<>();
private final List<CompensationInformation> compensationActivities = new ArrayList<>();
/**
* Build up a Saga with its options.
@ -59,7 +59,7 @@ public final class Saga {
if (activityClassName == null || activityClassName.isEmpty()) {
throw new IllegalArgumentException("activityClassName is required and should not be null or empty.");
}
this.compensationActivities.add(new CompensatationInformation(activityClassName, activityInput, taskOptions));
this.compensationActivities.add(new CompensationInformation(activityClassName, activityInput, taskOptions));
}
/**
@ -69,7 +69,7 @@ public final class Saga {
*/
public void compensate(WorkflowContext ctx) {
// Check if parallel compensation is enabled
// Specical case: when parallel compensation is enabled and there is only one
// Special case: when parallel compensation is enabled and there is only one
// compensation, we still
// compensate sequentially.
if (option.isParallelCompensation() && compensationActivities.size() > 1) {
@ -81,7 +81,7 @@ public final class Saga {
private void compensateInParallel(WorkflowContext ctx) {
List<Task<Void>> tasks = new ArrayList<>(compensationActivities.size());
for (CompensatationInformation compensationActivity : compensationActivities) {
for (CompensationInformation compensationActivity : compensationActivities) {
Task<Void> task = executeCompensateActivity(ctx, compensationActivity);
tasks.add(task);
}
@ -96,7 +96,7 @@ public final class Saga {
private void compensateSequentially(WorkflowContext ctx) {
SagaCompensationException sagaException = null;
for (int i = compensationActivities.size() - 1; i >= 0; i--) {
String activityClassName = compensationActivities.get(i).getCompensatationActivityClassName();
String activityClassName = compensationActivities.get(i).getCompensationActivityClassName();
try {
executeCompensateActivity(ctx, compensationActivities.get(i)).await();
} catch (OrchestratorBlockedException | ContinueAsNewInterruption e) {
@ -104,8 +104,7 @@ public final class Saga {
} catch (Exception e) {
if (sagaException == null) {
sagaException = new SagaCompensationException(
"Exception in saga compensatation: activity=" + activityClassName, e);
;
"Exception in saga compensation: activity=" + activityClassName, e);
} else {
sagaException.addSuppressed(e);
}
@ -121,10 +120,10 @@ public final class Saga {
}
}
private Task<Void> executeCompensateActivity(WorkflowContext ctx, CompensatationInformation info)
private Task<Void> executeCompensateActivity(WorkflowContext ctx, CompensationInformation info)
throws SagaCompensationException {
String activityClassName = info.getCompensatationActivityClassName();
return ctx.callActivity(activityClassName, info.getCompensatationActivityInput(),
String activityClassName = info.getCompensationActivityClassName();
return ctx.callActivity(activityClassName, info.getCompensationActivityInput(),
info.getTaskOptions());
}
}

View File

@ -92,8 +92,8 @@ public final class SagaOption {
}
/**
* Build Saga optiion.
* @return Saga optiion
* Build Saga option.
* @return Saga option
*/
public SagaOption build() {
return new SagaOption(this.parallelCompensation, this.maxParallelThread, this.continueWithError);

View File

@ -20,6 +20,7 @@ import com.microsoft.durabletask.TaskCanceledException;
import com.microsoft.durabletask.TaskOptions;
import com.microsoft.durabletask.TaskOrchestrationContext;
import io.dapr.workflows.runtime.DefaultWorkflowContext;
import io.dapr.workflows.saga.Saga;
import io.dapr.workflows.saga.SagaContext;
@ -43,15 +44,15 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class DaprWorkflowContextImplTest {
private DaprWorkflowContextImpl context;
public class DefaultWorkflowContextTest {
private DefaultWorkflowContext context;
private TaskOrchestrationContext mockInnerContext;
private WorkflowContext testWorkflowContext;
@BeforeEach
public void setUp() {
mockInnerContext = mock(TaskOrchestrationContext.class);
context = new DaprWorkflowContextImpl(mockInnerContext);
context = new DefaultWorkflowContext(mockInnerContext);
testWorkflowContext = new WorkflowContext() {
@Override
public Logger getLogger() {
@ -190,13 +191,13 @@ public class DaprWorkflowContextImplTest {
@Test
public void DaprWorkflowContextWithEmptyInnerContext() {
assertThrows(IllegalArgumentException.class, () -> {
context = new DaprWorkflowContextImpl(mockInnerContext, (Logger)null);
context = new DefaultWorkflowContext(mockInnerContext, (Logger)null);
}); }
@Test
public void DaprWorkflowContextWithEmptyLogger() {
assertThrows(IllegalArgumentException.class, () -> {
context = new DaprWorkflowContextImpl(null, (Logger)null);
context = new DefaultWorkflowContext(null, (Logger)null);
});
}
@ -216,7 +217,7 @@ public class DaprWorkflowContextImplTest {
public void getLoggerReplayingTest() {
Logger mockLogger = mock(Logger.class);
when(context.isReplaying()).thenReturn(true);
DaprWorkflowContextImpl testContext = new DaprWorkflowContextImpl(mockInnerContext, mockLogger);
DefaultWorkflowContext testContext = new DefaultWorkflowContext(mockInnerContext, mockLogger);
String expectedArg = "test print";
testContext.getLogger().info(expectedArg);
@ -228,7 +229,7 @@ public class DaprWorkflowContextImplTest {
public void getLoggerFirstTimeTest() {
Logger mockLogger = mock(Logger.class);
when(context.isReplaying()).thenReturn(false);
DaprWorkflowContextImpl testContext = new DaprWorkflowContextImpl(mockInnerContext, mockLogger);
DefaultWorkflowContext testContext = new DefaultWorkflowContext(mockInnerContext, mockLogger);
String expectedArg = "test print";
testContext.getLogger().info(expectedArg);
@ -322,7 +323,7 @@ public class DaprWorkflowContextImplTest {
@Test
public void getSagaContextTest_sagaEnabled() {
Saga saga = mock(Saga.class);
WorkflowContext context = new DaprWorkflowContextImpl(mockInnerContext, saga);
WorkflowContext context = new DefaultWorkflowContext(mockInnerContext, saga);
SagaContext sagaContext = context.getSagaContext();
assertNotNull("SagaContext should not be null", sagaContext);
@ -330,7 +331,7 @@ public class DaprWorkflowContextImplTest {
@Test
public void getSagaContextTest_sagaDisabled() {
WorkflowContext context = new DaprWorkflowContextImpl(mockInnerContext);
WorkflowContext context = new DefaultWorkflowContext(mockInnerContext);
assertThrows(UnsupportedOperationException.class, () -> {
context.getSagaContext();
});

View File

@ -162,7 +162,7 @@ public class WorkflowTest {
verify(sagaContext, times(1)).compensate();
}
public static class WorkflowWithoutSaga extends Workflow {
public static class WorkflowWithoutSaga implements Workflow {
private final WorkflowStub stub;
public WorkflowWithoutSaga(WorkflowStub stub) {
@ -175,7 +175,7 @@ public class WorkflowTest {
}
}
public static class WorkflowWithSaga extends Workflow {
public static class WorkflowWithSaga implements Workflow {
private final WorkflowStub stub;
public WorkflowWithSaga(WorkflowStub stub) {

View File

@ -44,7 +44,7 @@ public class DaprWorkflowClientTest {
private DurableTaskClient mockInnerClient;
private ManagedChannel mockGrpcChannel;
public static class TestWorkflow extends Workflow {
public static class TestWorkflow implements Workflow {
@Override
public WorkflowStub create() {
return WorkflowContext::getInstanceId;

View File

@ -1,6 +1,8 @@
package io.dapr.workflows.runtime;
import com.microsoft.durabletask.TaskActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
import org.junit.Assert;
import org.junit.Test;
@ -10,7 +12,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class ActivityWrapperTest {
public class WorkflowActivityWrapperTest {
public static class TestActivity implements WorkflowActivity {
@Override
public Object run(WorkflowActivityContext ctx) {
@ -21,10 +23,10 @@ public class ActivityWrapperTest {
@Test
public void getName() throws NoSuchMethodException {
ActivityWrapper<ActivityWrapperTest.TestActivity> wrapper = new ActivityWrapper<>(
ActivityWrapperTest.TestActivity.class);
WorkflowActivityWrapper<TestActivity> wrapper = new WorkflowActivityWrapper<>(
WorkflowActivityWrapperTest.TestActivity.class);
Assert.assertEquals(
"io.dapr.workflows.runtime.ActivityWrapperTest.TestActivity",
"io.dapr.workflows.runtime.WorkflowActivityWrapperTest.TestActivity",
wrapper.getName()
);
}
@ -32,8 +34,8 @@ public class ActivityWrapperTest {
@Test
public void createWithClass() throws NoSuchMethodException {
TaskActivityContext mockContext = mock(TaskActivityContext.class);
ActivityWrapper<ActivityWrapperTest.TestActivity> wrapper = new ActivityWrapper<>(
ActivityWrapperTest.TestActivity.class);
WorkflowActivityWrapper<TestActivity> wrapper = new WorkflowActivityWrapper<>(
WorkflowActivityWrapperTest.TestActivity.class);
when(mockContext.getInput(String.class)).thenReturn("Hello");
when(mockContext.getName()).thenReturn("TestActivityContext");
Object result = wrapper.create().run(mockContext);

View File

@ -14,6 +14,8 @@ package io.dapr.workflows.runtime;
import io.dapr.workflows.Workflow;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
import io.dapr.workflows.WorkflowStub;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
@ -25,7 +27,7 @@ import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
public class WorkflowRuntimeBuilderTest {
public static class TestWorkflow extends Workflow {
public static class TestWorkflow implements Workflow {
@Override
public WorkflowStub create() {
return ctx -> {

View File

@ -16,27 +16,17 @@ package io.dapr.workflows.runtime;
import com.microsoft.durabletask.DurableTaskGrpcWorker;
import com.microsoft.durabletask.DurableTaskGrpcWorkerBuilder;
import io.dapr.workflows.Workflow;
import io.dapr.workflows.WorkflowStub;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
public class WorkflowRuntimeTest {
public static class TestWorkflow extends Workflow {
@Override
public WorkflowStub create() {
return ctx -> { };
}
}
@Test
public void startTest() {
DurableTaskGrpcWorker worker = new DurableTaskGrpcWorkerBuilder().build();
try (WorkflowRuntime runtime = new WorkflowRuntime(worker)) {
assertDoesNotThrow(() -> {
runtime.start(false);
});
assertDoesNotThrow(() -> runtime.start(false));
}
}

View File

@ -26,8 +26,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class OrchestratorWrapperTest {
public static class TestWorkflow extends Workflow {
public class WorkflowWrapperTest {
public static class TestWorkflow implements Workflow {
@Override
public WorkflowStub create() {
return WorkflowContext::getInstanceId;
@ -36,9 +36,9 @@ public class OrchestratorWrapperTest {
@Test
public void getName() {
OrchestratorWrapper<TestWorkflow> wrapper = new OrchestratorWrapper<>(TestWorkflow.class);
WorkflowWrapper<TestWorkflow> wrapper = new WorkflowWrapper<>(TestWorkflow.class);
Assertions.assertEquals(
"io.dapr.workflows.runtime.OrchestratorWrapperTest.TestWorkflow",
"io.dapr.workflows.runtime.WorkflowWrapperTest.TestWorkflow",
wrapper.getName()
);
}
@ -46,7 +46,7 @@ public class OrchestratorWrapperTest {
@Test
public void createWithClass() {
TaskOrchestrationContext mockContext = mock(TaskOrchestrationContext.class);
OrchestratorWrapper<TestWorkflow> wrapper = new OrchestratorWrapper<>(TestWorkflow.class);
WorkflowWrapper<TestWorkflow> wrapper = new WorkflowWrapper<>(TestWorkflow.class);
when(mockContext.getInstanceId()).thenReturn("uuid");
wrapper.create().run(mockContext);
verify(mockContext, times(1)).getInstanceId();

View File

@ -6,11 +6,12 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import io.dapr.workflows.runtime.saga.DefaultSagaContext;
import org.junit.Test;
import io.dapr.workflows.WorkflowContext;
public class DaprSagaContextImplTest {
public class DefaultSagaContextTest {
@Test
public void testDaprSagaContextImpl_IllegalArgumentException() {
@ -18,11 +19,11 @@ public class DaprSagaContextImplTest {
WorkflowContext workflowContext = mock(WorkflowContext.class);
assertThrows(IllegalArgumentException.class, () -> {
new DaprSagaContextImpl(saga, null);
new DefaultSagaContext(saga, null);
});
assertThrows(IllegalArgumentException.class, () -> {
new DaprSagaContextImpl(null, workflowContext);
new DefaultSagaContext(null, workflowContext);
});
}
@ -30,7 +31,7 @@ public class DaprSagaContextImplTest {
public void test_registerCompensation() {
Saga saga = mock(Saga.class);
WorkflowContext workflowContext = mock(WorkflowContext.class);
DaprSagaContextImpl ctx = new DaprSagaContextImpl(saga, workflowContext);
DefaultSagaContext ctx = new DefaultSagaContext(saga, workflowContext);
String activityClassName = "name1";
Object activityInput = new Object();
@ -44,7 +45,7 @@ public class DaprSagaContextImplTest {
public void test_compensate() {
Saga saga = mock(Saga.class);
WorkflowContext workflowContext = mock(WorkflowContext.class);
DaprSagaContextImpl ctx = new DaprSagaContextImpl(saga, workflowContext);
DefaultSagaContext ctx = new DefaultSagaContext(saga, workflowContext);
doNothing().when(saga).compensate(workflowContext);

View File

@ -4,10 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.Test;
import com.microsoft.durabletask.TaskActivityContext;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
import io.dapr.workflows.WorkflowActivityContext;
public class SagaIntegrationTest {
@ -125,7 +123,7 @@ public class SagaIntegrationTest {
try {
Class<?> activityClass = Class.forName(activityClassName);
WorkflowActivity activity = (WorkflowActivity) activityClass.getDeclaredConstructor().newInstance();
WorkflowActivityContext ctx = new WorkflowActivityContext(new TaskActivityContext() {
WorkflowActivityContext ctx = new WorkflowActivityContext() {
@Override
public java.lang.String getName() {
@ -136,7 +134,7 @@ public class SagaIntegrationTest {
public <T> T getInput(Class<T> targetType) {
return (T) input;
}
});
};
randomFail();

View File

@ -32,6 +32,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import io.dapr.workflows.WorkflowActivityContext;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
@ -41,8 +42,7 @@ import com.microsoft.durabletask.Task;
import com.microsoft.durabletask.TaskOptions;
import io.dapr.workflows.WorkflowContext;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;
import io.dapr.workflows.WorkflowActivity;
public class SagaTest {