Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
- name: Maven release ${{steps.metadata.outputs.current-version}}
run: |
git checkout -b release
mvn -B release:prepare -Prelease -DreleaseVersion=${{steps.metadata.outputs.current-version}} -DdevelopmentVersion=${{steps.metadata.outputs.next-version}}
mvn -B release:prepare -DperformRelease -Prelease -DreleaseVersion=${{steps.metadata.outputs.current-version}} -DdevelopmentVersion=${{steps.metadata.outputs.next-version}}
cat release.properties
git checkout ${{github.base_ref}}
git rebase release
Expand Down
Binary file removed impl/test/db-samples/running.db
Binary file not shown.
Binary file removed impl/test/db-samples/running_v1.db
Binary file not shown.
Binary file removed impl/test/db-samples/suspended.db
Binary file not shown.
Binary file removed impl/test/db-samples/suspended_v1.db
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,25 @@
package io.serverlessworkflow.impl.test;

import static io.serverlessworkflow.api.WorkflowReader.readWorkflowFromClasspath;
import static org.awaitility.Awaitility.await;

import io.serverlessworkflow.impl.WorkflowApplication;
import io.serverlessworkflow.impl.WorkflowDefinition;
import io.serverlessworkflow.impl.WorkflowInstance;
import io.serverlessworkflow.impl.WorkflowStatus;
import io.serverlessworkflow.impl.persistence.PersistenceApplicationBuilder;
import io.serverlessworkflow.impl.persistence.PersistenceInstanceHandlers;
import io.serverlessworkflow.impl.persistence.bigmap.BytesMapPersistenceInstanceHandlers;
import io.serverlessworkflow.impl.persistence.mvstore.MVStorePersistenceStore;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Map;

public class DBGenerator {
public final class DBGenerator {

public static void main(String[] args) throws IOException {
runInstance("db-samples/running_v1.db", false);
runInstance("db-samples/suspended_v1.db", true);
}

private static void runInstance(String dbName, boolean suspend) throws IOException {
public static void generate(String dbName, boolean suspend) throws IOException {
Files.deleteIfExists(Path.of(dbName));
try (PersistenceInstanceHandlers factories =
BytesMapPersistenceInstanceHandlers.builder(new MVStorePersistenceStore(dbName))
Expand All @@ -51,8 +49,16 @@ private static void runInstance(String dbName, boolean suspend) throws IOExcepti
readWorkflowFromClasspath("workflows-samples/set-listen-to-any.yaml"));
WorkflowInstance instance = definition.instance(Map.of());
instance.start();

await()
.atMost(Duration.ofSeconds(5))
.until(() -> instance.status() == WorkflowStatus.WAITING);

if (suspend) {
instance.suspend();
await()
.atMost(Duration.ofSeconds(5))
.until(() -> instance.status() == WorkflowStatus.SUSPENDED);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification 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.serverlessworkflow.impl.test;

public final class DBGeneratorCli {
public static void main(String[] args) throws Exception {
if (args.length < 2) {
System.err.println("Usage: DBGeneratorCli <dbPath> <suspend:true|false>");
System.exit(2);
}
DBGenerator.generate(args[0], Boolean.parseBoolean(args[1]));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification 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.serverlessworkflow.impl.test;

import java.io.*;
import java.nio.file.*;
import java.util.Optional;

final class ForkedDbGen {
private static String detectJavaCmd() {
Optional<String> cmd = ProcessHandle.current().info().command();
if (cmd.isPresent() && Files.isRegularFile(Path.of(cmd.get()))) return cmd.get();
String home = System.getProperty("java.home");
String exe = System.getProperty("os.name").toLowerCase().contains("win") ? "java.exe" : "java";
Path p = Path.of(home, "bin", exe);
return Files.isRegularFile(p) ? p.toString() : "java";
}

static void run(Path db, boolean suspend) throws IOException, InterruptedException {
Files.createDirectories(db.getParent());
String javaCmd = detectJavaCmd();
String cp = System.getProperty("java.class.path");

ProcessBuilder pb =
new ProcessBuilder(
javaCmd,
"-cp",
cp,
DBGeneratorCli.class.getCanonicalName(),
db.toString(),
String.valueOf(suspend));
pb.redirectErrorStream(true);

Process p = pb.start();
try (BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
for (String line; (line = r.readLine()) != null; ) System.out.println("[dbgen] " + line);
}
int code = p.waitFor();
if (code != 0) throw new IllegalStateException("DB gen failed (" + code + ") for " + db);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,59 @@
import io.serverlessworkflow.impl.persistence.bigmap.BytesMapPersistenceInstanceHandlers;
import io.serverlessworkflow.impl.persistence.mvstore.MVStorePersistenceStore;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

public class MvStorePersistenceTest {
@Execution(ExecutionMode.SAME_THREAD)
class MvStorePersistenceTest {

@TempDir static Path tmp;

static Path runningV1, suspendedV1, runningV0, suspendedV0;

@BeforeAll
static void prepareDbSamples() throws IOException, InterruptedException {
runningV1 = tmp.resolve("running_v1.db");
suspendedV1 = tmp.resolve("suspended_v1.db");
runningV0 = tmp.resolve("running.db");
suspendedV0 = tmp.resolve("suspended.db");

ForkedDbGen.run(runningV1, false);
ForkedDbGen.run(suspendedV1, true);
ForkedDbGen.run(runningV0, false);
ForkedDbGen.run(suspendedV0, true);
}

@Test
void testSimpleRun() throws IOException {
final String dbName = "db-samples/simple.db";
final Path dbPath = tmp.resolve("simple.db");
try (PersistenceInstanceHandlers handlers =
BytesMapPersistenceInstanceHandlers.builder(new MVStorePersistenceStore(dbName))
BytesMapPersistenceInstanceHandlers.builder(
new MVStorePersistenceStore(dbPath.toString()))
.build();
WorkflowApplication application =
PersistenceApplicationBuilder.builder(WorkflowApplication.builder(), handlers.writer())
.build(); ) {
.build()) {

WorkflowDefinition definition =
application.workflowDefinition(
readWorkflowFromClasspath("workflows-samples/simple-expression.yaml"));

assertThat(handlers.reader().readAll(definition).values()).isEmpty();

definition.instance(Map.of()).start().join();

assertThat(handlers.reader().readAll(definition).values()).isEmpty();
} finally {
Files.delete(Path.of(dbName));
}
}

Expand All @@ -60,54 +88,57 @@ void testWaitingInstance() throws IOException {
TaskCounterPerInstanceListener taskCounter = new TaskCounterPerInstanceListener();
try (WorkflowApplication application =
WorkflowApplication.builder().withListener(taskCounter).build()) {

WorkflowDefinition definition =
application.workflowDefinition(
readWorkflowFromClasspath("workflows-samples/set-listen-to-any.yaml"));

WorkflowInstance instance = definition.instance(Map.of());
instance.start();

assertThat(taskCounter.taskCounter(instance.id()).completed()).isEqualTo(1);
}
}

@Test
void testRestoreWaitingInstanceV0() throws IOException {
runIt("db-samples/running.db", WorkflowStatus.WAITING);
@ParameterizedTest(name = "{index} ⇒ {0} should restore as {1}")
@MethodSource("dbSamples")
void testRestoreInstances(Path dbFile, WorkflowStatus expectedStatus) throws IOException {
runIt(dbFile, expectedStatus);
}

@Test
void testRestoreSuspendedInstanceV0() throws IOException {
runIt("db-samples/suspended.db", WorkflowStatus.SUSPENDED);
private static Stream<Arguments> dbSamples() {
return Stream.of(
Arguments.of(runningV0, WorkflowStatus.WAITING),
Arguments.of(suspendedV0, WorkflowStatus.SUSPENDED),
Arguments.of(runningV1, WorkflowStatus.WAITING),
Arguments.of(suspendedV1, WorkflowStatus.SUSPENDED));
}

@Test
void testRestoreWaitingInstanceV1() throws IOException {
runIt("db-samples/running_v1.db", WorkflowStatus.WAITING);
}

@Test
void testRestoreSuspendedInstanceV1() throws IOException {
runIt("db-samples/suspended_v1.db", WorkflowStatus.SUSPENDED);
}

private void runIt(String dbName, WorkflowStatus expectedStatus) throws IOException {
private void runIt(Path dbFile, WorkflowStatus expectedStatus) throws IOException {
TaskCounterPerInstanceListener taskCounter = new TaskCounterPerInstanceListener();

try (PersistenceInstanceHandlers handlers =
BytesMapPersistenceInstanceHandlers.builder(new MVStorePersistenceStore(dbName))
BytesMapPersistenceInstanceHandlers.builder(
new MVStorePersistenceStore(dbFile.toString()))
.build();
WorkflowApplication application =
PersistenceApplicationBuilder.builder(
WorkflowApplication.builder()
.withListener(taskCounter)
.withListener(new TraceExecutionListener()),
handlers.writer())
.build(); ) {
.build()) {

WorkflowDefinition definition =
application.workflowDefinition(
readWorkflowFromClasspath("workflows-samples/set-listen-to-any.yaml"));

Collection<WorkflowInstance> instances = handlers.reader().readAll(definition).values();

assertThat(instances).hasSize(1);

instances.forEach(WorkflowInstance::start);

assertThat(instances)
.singleElement()
.satisfies(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ do:
- callDoctor:
listen:
to:
any: []
any:
- with:
type: com.acme.any
13 changes: 12 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
<module>annotations</module>
<module>generators</module>
<module>serialization</module>
<module>examples</module>
<module>experimental</module>
<module>fluent</module>
<module>mermaid</module>
Expand Down Expand Up @@ -584,6 +583,18 @@
</pluginRepositories>

<profiles>
<profile>
<id>examples</id>
<activation>
<property>
<name>performRelease</name>
<value>!true</value>
</property>
</activation>
<modules>
<module>examples</module>
</modules>
</profile>
<profile>
<id>release</id>
<build>
Expand Down