Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic workflow #3

Merged
merged 6 commits into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
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
40 changes: 8 additions & 32 deletions src/main/java/io/xdb/core/client/BasicClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
import feign.Retryer;
import io.xdb.core.ServerErrorDecoder;
import io.xdb.core.exception.XDBHttpException;
import io.xdb.core.process.BasicClientProcessOptions;
import io.xdb.core.process.ProcessOptions;
import io.xdb.gen.api.ApiClient;
import io.xdb.gen.api.DefaultApi;
import io.xdb.gen.models.ProcessExecutionDescribeRequest;
import io.xdb.gen.models.ProcessExecutionDescribeResponse;
import io.xdb.gen.models.ProcessExecutionStartRequest;
import io.xdb.gen.models.ProcessExecutionStartResponse;
import io.xdb.gen.models.ProcessStartConfig;

/**
* {@link BasicClient} serves as a foundational client without a process {@link io.xdb.core.registry}.
Expand All @@ -30,33 +27,7 @@ public BasicClient(final ClientOptions clientOptions) {
this.defaultApi = buildDefaultApi();
}

public String startProcess(
final String processType,
final String processId,
final String startStateId,
final Object input,
final BasicClientProcessOptions processOptions
) {
final ProcessExecutionStartRequest request = new ProcessExecutionStartRequest()
.processType(processType)
.processId(processId)
.workerUrl(clientOptions.getWorkerUrl())
.startStateId(startStateId)
.startStateInput(clientOptions.getObjectEncoder().encode(input));

if (processOptions.getProcessOptionsOptional().isPresent()) {
final ProcessOptions options = processOptions.getProcessOptionsOptional().get();
request.processStartConfig(
new ProcessStartConfig()
.idReusePolicy(options.getProcessIdReusePolicy())
.timeoutSeconds(options.getTimeoutSeconds())
);
}

if (processOptions.getStartStateConfig().isPresent()) {
request.startStateConfig(processOptions.getStartStateConfig().get());
}

public String startProcess(final ProcessExecutionStartRequest request) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use xdb public request as the input to BasicClient to reduce the SDK side wrapper.

final ProcessExecutionStartResponse response;
try {
response = defaultApi.apiV1XdbServiceProcessExecutionStartPost(request);
Expand All @@ -67,8 +38,13 @@ public String startProcess(
return response.getProcessExecutionId();
}

public ProcessExecutionDescribeResponse describeCurrentProcessExecution(final String processId) {
final ProcessExecutionDescribeRequest request = new ProcessExecutionDescribeRequest().processId(processId);
public ProcessExecutionDescribeResponse describeCurrentProcessExecution(
final String namespace,
final String processId
) {
final ProcessExecutionDescribeRequest request = new ProcessExecutionDescribeRequest()
.namespace(namespace)
.processId(processId);

try {
return defaultApi.apiV1XdbServiceProcessExecutionDescribePost(request);
Expand Down
69 changes: 46 additions & 23 deletions src/main/java/io/xdb/core/client/Client.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package io.xdb.core.client;

import io.xdb.core.process.BasicClientProcessOptions;
import static io.xdb.core.process.ProcessOptions.DEFAULT_NAMESPACE;

import io.xdb.core.process.Process;
import io.xdb.core.process.ProcessOptions;
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 java.util.Optional;
import io.xdb.gen.models.ProcessExecutionDescribeResponse;
import io.xdb.gen.models.ProcessExecutionStartRequest;
import java.time.Duration;

public class Client {

Expand All @@ -24,7 +26,7 @@ public Client(final Registry registry, final ClientOptions clientOptions) {

public String startProcess(final Process process, final String processId, final Object input) {
final String processType = ProcessUtil.getProcessType(process);
return startProcessInternal(processType, processId, input, process.getOptions());
return startProcessInternal(processType, processId, input);
}

/**
Expand All @@ -40,31 +42,52 @@ public String startProcess(
final String processId,
final Object input
) {
final String processType = ProcessUtil.getProcessType(processClass);
return startProcessInternal(processType, processId, input, null);
final String processType = ProcessUtil.getClassSimpleName(processClass);
return startProcessInternal(processType, processId, input);
}

private String startProcessInternal(
final String processType,
final String processId,
final Object input,
final ProcessOptions processOptions
public ProcessExecutionDescribeResponse describeCurrentProcessExecution(final String processId) {
return describeCurrentProcessExecution(DEFAULT_NAMESPACE, processId);
}

public ProcessExecutionDescribeResponse describeCurrentProcessExecution(
final String namespace,
final String processId
) {
AsyncStateConfig asyncStateConfig = null;
String startingStateId = "";
return basicClient.describeCurrentProcessExecution(namespace, processId);
}

final Optional<AsyncState> startingState = registry.getProcessStartingState(processType);
if (startingState.isPresent()) {
asyncStateConfig =
new AsyncStateConfig().skipWaitUntil(AsyncState.shouldSkipWaitUntil(startingState.get()));
startingStateId = ProcessUtil.getStateId(startingState.get());
// 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);
final ProcessOptions processOptions = process.getOptions() == null
? ProcessOptions.builder(process.getClass()).build()
: process.getOptions();

final BasicClientProcessOptions basicClientProcessOptions = new BasicClientProcessOptions(
processOptions,
asyncStateConfig
);
final ProcessExecutionStartRequest request = new ProcessExecutionStartRequest()
.namespace(processOptions.getNamespace())
.processId(processId)
.processType(processType)
.workerUrl(clientOptions.getWorkerUrl())
.startStateInput(clientOptions.getObjectEncoder().encode(input))
.processStartConfig(processOptions.getProcessStartConfig());

if (process.getStateSchema() != null && process.getStateSchema().getStartingState() != null) {
final AsyncState startingState = process.getStateSchema().getStartingState();
request
.startStateId(ProcessUtil.getStateId(startingState))
.startStateConfig(ProcessUtil.getAsyncStateConfig(startingState));
}

return basicClient.startProcess(processType, processId, startingStateId, input, basicClientProcessOptions);
return basicClient.startProcess(request);
}
}
17 changes: 0 additions & 17 deletions src/main/java/io/xdb/core/process/BasicClientProcessOptions.java

This file was deleted.

2 changes: 1 addition & 1 deletion src/main/java/io/xdb/core/process/Process.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/
public interface Process {
default ProcessOptions getOptions() {
return ProcessOptions.builder().build();
return ProcessOptions.builder(this.getClass()).build();
}

default StateSchema getStateSchema() {
Expand Down
43 changes: 38 additions & 5 deletions src/main/java/io/xdb/core/process/ProcessOptions.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,47 @@
package io.xdb.core.process;

import io.xdb.gen.models.ProcessIdReusePolicy;
import com.google.common.base.Strings;
import io.xdb.core.exception.ProcessDefinitionException;
import io.xdb.core.utils.ProcessUtil;
import io.xdb.gen.models.ProcessStartConfig;
import lombok.Builder;
import lombok.Getter;

@Builder
@Getter
public class ProcessOptions {

// either processClass or type must be set
private final Class<? extends Process> processClass;
// If not set, use the default value.
private final String namespace;
// either processClass or type must be set
private final String type;
private final ProcessIdReusePolicy processIdReusePolicy;
private final Integer timeoutSeconds;
private final ProcessStartConfig processStartConfig;

public static final String DEFAULT_NAMESPACE = "default";

public static ProcessOptionsBuilder builder(final Class<? extends Process> processClass) {
return builder().processClass(processClass);
}

private static ProcessOptionsBuilder builder() {
return new ProcessOptionsBuilder();
}

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

public String getType() {
return Strings.isNullOrEmpty(type) ? ProcessUtil.getClassSimpleName(processClass) : type;
}

public ProcessStartConfig getProcessStartConfig() {
return processStartConfig;
}

public void validate() {
if (processClass == null && Strings.isNullOrEmpty(type)) {
throw new ProcessDefinitionException("ProcessOptions: either processClass or type must be set.");
}
}
}
33 changes: 21 additions & 12 deletions src/main/java/io/xdb/core/registry/Registry.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
import io.xdb.core.utils.ProcessUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import lombok.Getter;

@Getter
public class Registry {

// process type: process
Expand Down Expand Up @@ -37,20 +34,24 @@ public Process getProcess(final String type) {
return processStore.get(type);
}

public Optional<AsyncState> getProcessStartingState(final String type) {
final Process process = getProcess(type);
final AsyncState startingState = process.getStateSchema().getStartingState();
if (startingState == null) {
return Optional.empty();
}
return Optional.of(startingState);
}

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);
}

private void registerProcess(final Process process) {
if (process.getOptions() != null) {
process.getOptions().validate();
}

final String type = ProcessUtil.getProcessType(process);

if (processStore.containsKey(type)) {
Expand All @@ -63,11 +64,19 @@ private void registerProcess(final Process process) {
}

private void registerProcessStates(final Process process) {
if (process.getStateSchema() == null) {
return;
}

final String processType = ProcessUtil.getProcessType(process);

final HashMap<String, AsyncState> stateMap = new HashMap<>();

for (final AsyncState state : process.getStateSchema().getAllStates()) {
if (state.getOptions() != null) {
state.getOptions().validate();
}

final String stateId = ProcessUtil.getStateId(state);

if (stateMap.containsKey(stateId)) {
Expand Down
5 changes: 2 additions & 3 deletions 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;

public interface AsyncState<I> {
Expand All @@ -16,8 +15,8 @@ public interface AsyncState<I> {
*
* @return the state options
*/
default StateOptions getOptions() {
return StateOptions.builder().build();
default AsyncStateOptions getOptions() {
return AsyncStateOptions.builder(this.getClass()).build();
}

/**
Expand Down
Loading