Skip to content

Commit

Permalink
add integ test
Browse files Browse the repository at this point in the history
  • Loading branch information
zklgame committed Oct 7, 2023
1 parent 76b347b commit 3647b42
Show file tree
Hide file tree
Showing 26 changed files with 467 additions and 180 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Test Build
name: Integration Test
on:
pull_request:
push:
Expand All @@ -7,10 +7,12 @@ on:

jobs:
tests:
name: "Test build"
name: "Integration Test"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: "Set up xdb environment"
run: wget https://raw.githubusercontent.com/xdblab/xdb/main/docker-compose/docker-compose-postgres14-example.yaml && docker compose -f docker-compose-postgres14-example.yaml up -d
- uses: actions/setup-java@v3
with:
distribution: zulu
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# xdb-java-sdk

[![Coverage Status](https://codecov.io/github/xdblab/xdb-java-sdk/coverage.svg?branch=main)](https://app.codecov.io/gh/xdblab/xdb-java-sdk/branch/main)
[![Build status](https://github.com/xdblab/xdb-java-sdk/actions/workflows/ci-test.yml/badge.svg?branch=main)](https://github.com/xdblab/xdb-java-sdk/actions/workflows/ci-test.yml)
[![Build status](https://github.com/xdblab/xdb-java-sdk/actions/workflows/ci-integ-test.yml/badge.svg?branch=main)](https://github.com/xdblab/xdb-java-sdk/actions/workflows/ci-integ-test.yml)

Java SDK for [xdb](https://github.com/xdblab/xdb)

Expand Down
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ plugins {
id 'signing'
id 'jacoco'
id 'com.diffplug.spotless' version "6.13.0"
id "org.springframework.boot" version "2.7.16"
}

bootJar {
enabled = false
}

java {
Expand Down Expand Up @@ -46,6 +51,7 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
testCompileOnly 'org.projectlombok:lombok:1.18.30'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.30'
testImplementation 'org.springframework.boot:spring-boot-starter-web:2.7.16'
}

// open api
Expand Down
20 changes: 17 additions & 3 deletions src/main/java/io/xdb/core/client/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import io.xdb.core.registry.Registry;
import io.xdb.core.state.AsyncState;
import io.xdb.core.utils.ProcessUtil;
import io.xdb.gen.models.AsyncStateConfig;
import io.xdb.gen.models.ProcessExecutionDescribeResponse;
import io.xdb.gen.models.ProcessExecutionStartRequest;
import java.time.Duration;

public class Client {

Expand Down Expand Up @@ -39,17 +39,31 @@ public String startProcess(
final String processId,
final Object input
) {
final String processType = ProcessUtil.getClassSimpleName(processClass);
final String processType = ProcessUtil.getProcessType(processClass);
return startProcessInternal(processType, processId, input);
}

public ProcessExecutionDescribeResponse describeCurrentProcessExecution(final String processId) {
return describeCurrentProcessExecution(ProcessUtil.DEFAULT_NAMESPACE, processId);
}

public ProcessExecutionDescribeResponse describeCurrentProcessExecution(
final String namespace,
final String processId
) {
return basicClient.describeCurrentProcessExecution(namespace, processId);
}

// TODO: placeholder to be used in integration test for now
public void getProcessResultWithWait(final String processId) {
System.out.println(processId);
try {
Thread.sleep(Duration.ofSeconds(2).toMillis());
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
}

private String startProcessInternal(final String processType, final String processId, final Object input) {
final Process process = registry.getProcess(processType);

Expand All @@ -65,7 +79,7 @@ private String startProcessInternal(final String processType, final String proce
if (startingState != null) {
request
.startStateId(startingState.getOptions().getId(startingState.getClass()))
.startStateConfig(new AsyncStateConfig().skipWaitUntil(AsyncState.shouldSkipWaitUntil(startingState)));
.startStateConfig(ProcessUtil.getAsyncStateConfig(startingState));
}

return basicClient.startProcess(request);
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/io/xdb/core/process/ProcessOptions.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.xdb.core.process;

import static io.xdb.core.utils.ProcessUtil.DEFAULT_NAMESPACE;

import com.google.common.base.Strings;
import io.xdb.core.utils.ProcessUtil;
import io.xdb.gen.models.ProcessStartConfig;
Expand All @@ -14,11 +16,11 @@ public class ProcessOptions {
private final ProcessStartConfig processStartConfig;

public String getNamespace() {
return Strings.isNullOrEmpty(namespace) ? "default" : namespace;
return Strings.isNullOrEmpty(namespace) ? DEFAULT_NAMESPACE : namespace;
}

public String getType(final Class<? extends Process> processClass) {
return Strings.isNullOrEmpty(type) ? ProcessUtil.getClassSimpleName(processClass) : type;
return Strings.isNullOrEmpty(type) ? ProcessUtil.getProcessType(processClass) : type;
}

public ProcessStartConfig getProcessStartConfig() {
Expand Down
11 changes: 9 additions & 2 deletions src/main/java/io/xdb/core/registry/Registry.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
import io.xdb.core.state.AsyncState;
import java.util.HashMap;
import java.util.Map;
import lombok.Getter;

@Getter
public class Registry {

// process type: process
Expand Down Expand Up @@ -36,6 +34,15 @@ public Process getProcess(final String type) {
}

public AsyncState getProcessState(final String type, final String stateId) {
if (!processStatesStore.containsKey(type) || !processStatesStore.get(type).containsKey(stateId)) {
throw new ProcessDefinitionException(
String.format(
"Process type %s or state id %s has not been registered in processStatesStore.",
type,
stateId
)
);
}
return processStatesStore.get(type).get(stateId);
}

Expand Down
1 change: 0 additions & 1 deletion src/main/java/io/xdb/core/state/AsyncState.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.xdb.core.state;

import io.xdb.gen.models.CommandRequest;
import io.xdb.gen.models.StateDecision;
import java.lang.reflect.Method;
import lombok.NonNull;

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/xdb/core/state/AsyncStateOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ public class AsyncStateOptions {
private final String id;

public String getId(final Class<? extends AsyncState> stateClass) {
return Strings.isNullOrEmpty(id) ? ProcessUtil.getClassSimpleName(stateClass) : id;
return Strings.isNullOrEmpty(id) ? ProcessUtil.getStateId(stateClass) : id;
}
}
96 changes: 96 additions & 0 deletions src/main/java/io/xdb/core/state/StateDecision.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package io.xdb.core.state;

import com.google.common.collect.ImmutableList;
import io.xdb.core.utils.ProcessUtil;
import io.xdb.gen.models.ThreadCloseDecision;
import io.xdb.gen.models.ThreadCloseType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Builder;
import lombok.Getter;

@Builder
@Getter
public class StateDecision {

// directly return stateDecision if it presents
private final io.xdb.gen.models.StateDecision stateDecision;
private final List<StateMovement> nextStates;

public static StateDecision deadEnd() {
return StateDecision
.builder()
.stateDecision(
new io.xdb.gen.models.StateDecision()
.threadCloseDecision(new ThreadCloseDecision().closeType(ThreadCloseType.DEAD_END))
)
.build();
}

public static StateDecision gracefulCompleteProcess() {
return StateDecision
.builder()
.stateDecision(
new io.xdb.gen.models.StateDecision()
.threadCloseDecision(new ThreadCloseDecision().closeType(ThreadCloseType.GRACEFUL_COMPLETE_PROCESS))
)
.build();
}

public static StateDecision forceCompleteProcess() {
return StateDecision
.builder()
.stateDecision(
new io.xdb.gen.models.StateDecision()
.threadCloseDecision(new ThreadCloseDecision().closeType(ThreadCloseType.FORCE_COMPLETE_PROCESS))
)
.build();
}

public static StateDecision forceFailProcess() {
return StateDecision
.builder()
.stateDecision(
new io.xdb.gen.models.StateDecision()
.threadCloseDecision(new ThreadCloseDecision().closeType(ThreadCloseType.FORCE_FAIL_PROCESS))
)
.build();
}

// TODO: option override
public static StateDecision singleNextState(final Class<? extends AsyncState> stateClass, final Object stateInput) {
final StateMovement stateMovement = StateMovement
.builder()
.stateId(ProcessUtil.getStateId(stateClass))
.stateInput(stateInput)
.build();
return StateDecision.builder().nextStates(ImmutableList.of(stateMovement)).build();
}

public static StateDecision singleNextState(final String stateId, final Object stateInput) {
final StateMovement stateMovement = StateMovement.builder().stateId(stateId).stateInput(stateInput).build();
return StateDecision.builder().nextStates(ImmutableList.of(stateMovement)).build();
}

public static StateDecision multipleNextStates(final Class<? extends AsyncState>... stateClasses) {
final ArrayList<StateMovement> stateMovements = new ArrayList<>();
for (final Class<? extends AsyncState> stateClass : stateClasses) {
stateMovements.add(StateMovement.builder().stateId(ProcessUtil.getStateId(stateClass)).build());
}
return StateDecision.builder().nextStates(stateMovements).build();
}

public static StateDecision multipleNextStates(final String... stateIds) {
final ArrayList<StateMovement> stateMovements = new ArrayList<>();
for (final String stateId : stateIds) {
stateMovements.add(StateMovement.builder().stateId(stateId).build());
}
return StateDecision.builder().nextStates(stateMovements).build();
}

public static StateDecision multipleNextStates(final StateMovement... stateMovements) {
return StateDecision.builder().nextStates(Arrays.stream(stateMovements).collect(Collectors.toList())).build();
}
}
12 changes: 12 additions & 0 deletions src/main/java/io/xdb/core/state/StateMovement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.xdb.core.state;

import lombok.Builder;
import lombok.Getter;

@Builder
@Getter
public class StateMovement {

private final String stateId;
private final Object stateInput;
}
19 changes: 16 additions & 3 deletions src/main/java/io/xdb/core/utils/ProcessUtil.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
package io.xdb.core.utils;

// mainly to return default values for null cases
import io.xdb.core.process.Process;
import io.xdb.core.state.AsyncState;
import io.xdb.gen.models.AsyncStateConfig;

public class ProcessUtil {

public static String getClassSimpleName(final Class<?> obejctClass) {
return obejctClass.getSimpleName();
public static final String DEFAULT_NAMESPACE = "default";

public static String getProcessType(final Class<? extends Process> processClass) {
return processClass.getSimpleName();
}

public static String getStateId(final Class<? extends AsyncState> stateClass) {
return stateClass.getSimpleName();
}

public static AsyncStateConfig getAsyncStateConfig(final AsyncState state) {
return new AsyncStateConfig().skipWaitUntil(AsyncState.shouldSkipWaitUntil(state));
}
}
31 changes: 29 additions & 2 deletions src/main/java/io/xdb/core/worker/WorkerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

import io.xdb.core.registry.Registry;
import io.xdb.core.state.AsyncState;
import io.xdb.core.utils.ProcessUtil;
import io.xdb.gen.models.AsyncStateExecuteRequest;
import io.xdb.gen.models.AsyncStateExecuteResponse;
import io.xdb.gen.models.AsyncStateWaitUntilRequest;
import io.xdb.gen.models.AsyncStateWaitUntilResponse;
import io.xdb.gen.models.CommandRequest;
import io.xdb.gen.models.StateDecision;
import io.xdb.gen.models.StateMovement;
import java.util.List;
import java.util.stream.Collectors;

public class WorkerService {

Expand Down Expand Up @@ -41,8 +45,31 @@ public AsyncStateExecuteResponse handleAsyncStateExecute(final AsyncStateExecute
.decode(request.getStateInput(), state.getInputType());

// TODO
final StateDecision stateDecision = state.execute(input);
final io.xdb.core.state.StateDecision stateDecision = state.execute(input);

return new AsyncStateExecuteResponse().stateDecision(stateDecision);
return new AsyncStateExecuteResponse().stateDecision(toServerModel(request.getProcessType(), stateDecision));
}

private StateDecision toServerModel(final String processType, final io.xdb.core.state.StateDecision stateDecision) {
if (stateDecision.getStateDecision() != null) {
return stateDecision.getStateDecision();
}

final List<StateMovement> stateMovements = stateDecision
.getNextStates()
.stream()
.map(stateMovement ->
new StateMovement()
.stateId(stateMovement.getStateId())
.stateInput(workerServiceOptions.getObjectEncoder().encode(stateMovement.getStateInput()))
.stateConfig(
ProcessUtil.getAsyncStateConfig(
registry.getProcessState(processType, stateMovement.getStateId())
)
)
)
.collect(Collectors.toList());

return new StateDecision().nextStates(stateMovements);
}
}
Loading

0 comments on commit 3647b42

Please sign in to comment.