From 69769cb2f19f3863690c006bead6ab948f8d1a2d Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Fri, 21 Jun 2024 09:22:46 -0700 Subject: [PATCH] Fix empty-string fields on CaN not working (#2120) --- .../internal/testservice/StateMachines.java | 4 +- .../functional/ContinueAsNewTest.java | 118 ++++++++++++++++++ .../functional/common/TestWorkflows.java | 6 + 3 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 temporal-test-server/src/test/java/io/temporal/testserver/functional/ContinueAsNewTest.java diff --git a/temporal-test-server/src/main/java/io/temporal/internal/testservice/StateMachines.java b/temporal-test-server/src/main/java/io/temporal/internal/testservice/StateMachines.java index f58482f21..e26641552 100644 --- a/temporal-test-server/src/main/java/io/temporal/internal/testservice/StateMachines.java +++ b/temporal-test-server/src/main/java/io/temporal/internal/testservice/StateMachines.java @@ -936,12 +936,12 @@ private static void continueAsNewWorkflow( } else { a.setWorkflowRunTimeout(sr.getWorkflowRunTimeout()); } - if (d.hasTaskQueue()) { + if (d.hasTaskQueue() && !d.getTaskQueue().getName().isEmpty()) { a.setTaskQueue(d.getTaskQueue()); } else { a.setTaskQueue(sr.getTaskQueue()); } - if (d.hasWorkflowType()) { + if (d.hasWorkflowType() && !d.getWorkflowType().getName().isEmpty()) { a.setWorkflowType(d.getWorkflowType()); } else { a.setWorkflowType(sr.getWorkflowType()); diff --git a/temporal-test-server/src/test/java/io/temporal/testserver/functional/ContinueAsNewTest.java b/temporal-test-server/src/test/java/io/temporal/testserver/functional/ContinueAsNewTest.java new file mode 100644 index 000000000..f97060f04 --- /dev/null +++ b/temporal-test-server/src/test/java/io/temporal/testserver/functional/ContinueAsNewTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved. + * + * Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Modifications copyright (C) 2017 Uber Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this material 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.temporal.testserver.functional; + +import io.temporal.api.common.v1.WorkflowExecution; +import io.temporal.client.WorkflowOptions; +import io.temporal.client.WorkflowStub; +import io.temporal.common.WorkflowExecutionHistory; +import io.temporal.common.interceptors.*; +import io.temporal.testing.internal.SDKTestWorkflowRule; +import io.temporal.testserver.functional.common.TestWorkflows; +import io.temporal.worker.WorkerFactoryOptions; +import io.temporal.workflow.ContinueAsNewOptions; +import io.temporal.workflow.Workflow; +import java.time.Duration; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; + +public class ContinueAsNewTest { + + @Rule + public SDKTestWorkflowRule testWorkflowRule = + SDKTestWorkflowRule.newBuilder() + .setWorkerFactoryOptions( + WorkerFactoryOptions.newBuilder() + .setWorkerInterceptors(new StripsTqFromCanInterceptor()) + .build()) + .setWorkflowTypes(TestWorkflow.class) + .build(); + + @Test + public void repeatedFailure() { + WorkflowOptions options = + WorkflowOptions.newBuilder() + .setWorkflowTaskTimeout(Duration.ofSeconds(1)) + .setTaskQueue(testWorkflowRule.getTaskQueue()) + .build(); + + TestWorkflows.WorkflowTakesBool workflowStub = + testWorkflowRule + .getWorkflowClient() + .newWorkflowStub(TestWorkflows.WorkflowTakesBool.class, options); + workflowStub.execute(true); + + WorkflowExecution execution = WorkflowStub.fromTyped(workflowStub).getExecution(); + // Verify the latest history is from being CaN'd + WorkflowExecutionHistory lastHist = + testWorkflowRule.getExecutionHistory(execution.getWorkflowId()); + Assert.assertFalse( + lastHist + .getEvents() + .get(0) + .getWorkflowExecutionStartedEventAttributes() + .getFirstExecutionRunId() + .isEmpty()); + } + + public static class TestWorkflow implements TestWorkflows.WorkflowTakesBool { + @Override + public void execute(boolean doContinue) { + if (doContinue) { + Workflow.continueAsNew(false); + } + } + } + + // Verify that we can strip the TQ name and test server continues onto same TQ + private static class StripsTqFromCanInterceptor extends WorkerInterceptorBase { + @Override + public WorkflowInboundCallsInterceptor interceptWorkflow(WorkflowInboundCallsInterceptor next) { + return new WorkflowInboundCallsInterceptorBase(next) { + @Override + public void init(WorkflowOutboundCallsInterceptor outboundCalls) { + next.init(new StripsTqFromCanCmd(outboundCalls)); + } + }; + } + } + + private static class StripsTqFromCanCmd extends WorkflowOutboundCallsInterceptorBase { + + private final WorkflowOutboundCallsInterceptor next; + + public StripsTqFromCanCmd(WorkflowOutboundCallsInterceptor next) { + super(next); + this.next = next; + } + + @Override + public void continueAsNew(ContinueAsNewInput input) { + next.continueAsNew( + new ContinueAsNewInput( + input.getWorkflowType(), + ContinueAsNewOptions.newBuilder(input.getOptions()).setTaskQueue("").build(), + input.getArgs(), + input.getHeader())); + } + } +} diff --git a/temporal-test-server/src/test/java/io/temporal/testserver/functional/common/TestWorkflows.java b/temporal-test-server/src/test/java/io/temporal/testserver/functional/common/TestWorkflows.java index fd9e9e403..b67154d65 100644 --- a/temporal-test-server/src/test/java/io/temporal/testserver/functional/common/TestWorkflows.java +++ b/temporal-test-server/src/test/java/io/temporal/testserver/functional/common/TestWorkflows.java @@ -30,6 +30,12 @@ public interface PrimitiveWorkflow { void execute(); } + @WorkflowInterface + public interface WorkflowTakesBool { + @WorkflowMethod + void execute(boolean arg); + } + @WorkflowInterface public interface WorkflowReturnsString { @WorkflowMethod