Skip to content

Commit

Permalink
fix: workflows, exception when running a step with a null workflow st…
Browse files Browse the repository at this point in the history
…ate (#1767)
  • Loading branch information
aludwiko authored Aug 21, 2023
1 parent 2d2ed22 commit 2886e7c
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,10 @@ final class WorkflowImpl(system: ActorSystem, val services: Map[String, Workflow
val timerScheduler = new TimerSchedulerImpl(service.messageCodec, system)
val stepResponse =
try {
val decoded = service.messageCodec.decodeMessage(executeStep.userState.get)
router._internalSetInitState(decoded, false) // here we know that workflow is still running
executeStep.userState.foreach { state =>
val decoded = service.messageCodec.decodeMessage(state)
router._internalSetInitState(decoded, finished = false) // here we know that workflow is still running
}
router._internalHandleStep(
executeStep.commandId,
executeStep.input,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,26 @@ public void shouldNotUpdateWorkflowStateAfterEndTransition() {
assertThat(execute(componentClient.forWorkflow(workflowId).call(DummyWorkflow::get))).isEqualTo(10);
}

@Test
public void shouldRunWorkflowStepWithoutInitialState() {
//given
var workflowId = randomId();

//when
String response = execute(componentClient.forWorkflow(workflowId)
.call(WorkflowWithoutInitialState::start));

assertThat(response).contains("ok");

//then
await()
.atMost(10, TimeUnit.of(SECONDS))
.untilAsserted(() -> {
var state = execute(componentClient.forWorkflow(workflowId).call(WorkflowWithoutInitialState::get));
assertThat(state).contains("success");
});
}

private <T> T execute(DeferredCall<Any, T> deferredCall) {
return execute(deferredCall, timeout);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2021 Lightbend 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.example.wiring.workflowentities;

import kalix.javasdk.annotations.Id;
import kalix.javasdk.annotations.TypeId;
import kalix.javasdk.client.ComponentClient;
import kalix.javasdk.workflow.Workflow;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.concurrent.CompletableFuture;

@Id("id")
@TypeId("workflow-without-initial-state")
@RequestMapping("/workflow-without-initial-state/{id}")
public class WorkflowWithoutInitialState extends Workflow<String> {


private ComponentClient componentClient;

public WorkflowWithoutInitialState(ComponentClient componentClient) {
this.componentClient = componentClient;
}

@Override
public WorkflowDef<String> definition() {
var test =
step("test")
.asyncCall(() -> CompletableFuture.completedFuture("ok"))
.andThen(String.class, result -> effects().updateState("success").end());

return workflow()
.addStep(test);
}

@PutMapping()
public Effect<String> start() {
return effects().transitionTo("test").thenReply("ok");
}

@GetMapping()
public Effect<String> get() {
if (currentState() == null) {
return effects().reply("empty");
} else {
return effects().reply(currentState());
}
}
}

0 comments on commit 2886e7c

Please sign in to comment.