From a4173d92ca72b761728e4f7add66a80d6500a7f9 Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Thu, 17 Jul 2025 20:41:35 -0700 Subject: [PATCH 1/2] Add client API --- .../client/CancelOperationOptions.java | 41 +++++++ .../client/ExecuteOperationOptions.java | 103 ++++++++++++++++++ .../client/GetOperationInfoOptions.java | 40 +++++++ .../client/GetOperationResultOptions.java | 59 ++++++++++ .../io/nexusrpc/client/GetResultResponse.java | 45 ++++++++ .../io/nexusrpc/client/OperationHandle.java | 35 ++++++ .../io/nexusrpc/client/ServiceClient.java | 65 +++++++++++ .../client/StartOperationOptions.java | 89 +++++++++++++++ .../nexusrpc/client/StartOperationResult.java | 21 ++++ 9 files changed, 498 insertions(+) create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/CancelOperationOptions.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/ExecuteOperationOptions.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/GetOperationInfoOptions.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/GetOperationResultOptions.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/GetResultResponse.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/OperationHandle.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/ServiceClient.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationOptions.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationResult.java diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/CancelOperationOptions.java b/nexus-sdk/src/main/java/io/nexusrpc/client/CancelOperationOptions.java new file mode 100644 index 0000000..a56a8f2 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/CancelOperationOptions.java @@ -0,0 +1,41 @@ +package io.nexusrpc.client; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +/** CancelOperationOptions is used to specify options for canceling an operation. */ +public class CancelOperationOptions { + /** Create a builder for CancelOperationOptions. */ + public static CancelOperationOptions.Builder newBuilder() { + return new CancelOperationOptions.Builder(); + } + + private final SortedMap headers; + + private CancelOperationOptions(SortedMap headers) { + this.headers = headers; + } + + /** Headers. The returned map operates without regard to case. */ + public Map getHeaders() { + return headers; + } + + public static class Builder { + private final SortedMap headers; + + private Builder() { + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + } + + /** Get headers to mutate. */ + public Map getHeaders() { + return headers; + } + + public CancelOperationOptions build() { + return new CancelOperationOptions(headers); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/ExecuteOperationOptions.java b/nexus-sdk/src/main/java/io/nexusrpc/client/ExecuteOperationOptions.java new file mode 100644 index 0000000..69706f9 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/ExecuteOperationOptions.java @@ -0,0 +1,103 @@ +package io.nexusrpc.client; + +import io.nexusrpc.Link; +import java.time.Duration; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class ExecuteOperationOptions { + private final Map headers; + private final String callbackURL; + private final Map callbackHeaders; + private final String requestId; + private final List inboundLinks; + private final Duration timeout; + + public ExecuteOperationOptions( + Map headers, + String callbackURL, + Map callbackHeaders, + String requestId, + List inboundLinks, + Duration timeout) { + this.headers = headers; + this.callbackURL = callbackURL; + this.callbackHeaders = callbackHeaders; + this.requestId = requestId; + this.inboundLinks = inboundLinks; + this.timeout = timeout; + } + + public Map getHeaders() { + return headers; + } + + public String getCallbackURL() { + return callbackURL; + } + + public Map getCallbackHeaders() { + return callbackHeaders; + } + + public String getRequestId() { + return requestId; + } + + public List getInboundLinks() { + return inboundLinks; + } + + public Duration getTimeout() { + return timeout; + } + + public static class Builder { + private final SortedMap headers; + private String callbackURL; + private SortedMap callbackHeaders; + private String requestId; + private List inboundLinks; + private Duration timeout; + + public Builder() { + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + callbackHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + } + + public Map getHeaders() { + return headers; + } + + public Builder setCallbackURL(String callbackURL) { + this.callbackURL = callbackURL; + return this; + } + + public Map getCallbackHeaders() { + return callbackHeaders; + } + + public Builder setRequestId(String requestId) { + this.requestId = requestId; + return this; + } + + public Builder setInboundLinks(List inboundLinks) { + this.inboundLinks = inboundLinks; + return this; + } + + public Builder setTimeout(Duration timeout) { + this.timeout = timeout; + return this; + } + + public ExecuteOperationOptions build() { + return new ExecuteOperationOptions( + headers, callbackURL, callbackHeaders, requestId, inboundLinks, timeout); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/GetOperationInfoOptions.java b/nexus-sdk/src/main/java/io/nexusrpc/client/GetOperationInfoOptions.java new file mode 100644 index 0000000..d230195 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/GetOperationInfoOptions.java @@ -0,0 +1,40 @@ +package io.nexusrpc.client; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class GetOperationInfoOptions { + /** Create a builder for CancelOperationOptions. */ + public static GetOperationInfoOptions.Builder newBuilder() { + return new GetOperationInfoOptions.Builder(); + } + + private final SortedMap headers; + + private GetOperationInfoOptions(SortedMap headers) { + this.headers = headers; + } + + /** Headers. The returned map operates without regard to case. */ + public Map getHeaders() { + return headers; + } + + public static class Builder { + private final SortedMap headers; + + private Builder() { + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + } + + /** Get headers to mutate. */ + public Map getHeaders() { + return headers; + } + + public GetOperationInfoOptions build() { + return new GetOperationInfoOptions(headers); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/GetOperationResultOptions.java b/nexus-sdk/src/main/java/io/nexusrpc/client/GetOperationResultOptions.java new file mode 100644 index 0000000..30e913f --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/GetOperationResultOptions.java @@ -0,0 +1,59 @@ +package io.nexusrpc.client; + +import java.time.Duration; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class GetOperationResultOptions { + /** Create a builder for GetOperationResultOptions. */ + public static GetOperationResultOptions.Builder newBuilder() { + return new GetOperationResultOptions.Builder(); + } + + private final Duration timeout; + private final SortedMap headers; + + private GetOperationResultOptions(Duration timeout, SortedMap headers) { + this.timeout = timeout; + this.headers = headers; + } + + /** Headers. The returned map operates without regard to case. */ + public Map getHeaders() { + return headers; + } + + public Duration getTimeout() { + return timeout; + } + + public static class Builder { + private final SortedMap headers; + private Duration timeout; + + private Builder() { + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + } + + /** Get headers to mutate. */ + public Map getHeaders() { + return headers; + } + + /** + * Set the timeout for the operation. + * + * @param timeout the duration to wait for the operation result + * @return this builder instance + */ + public Builder setTimeout(Duration timeout) { + this.timeout = timeout; + return this; + } + + public GetOperationResultOptions build() { + return new GetOperationResultOptions(timeout, headers); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/GetResultResponse.java b/nexus-sdk/src/main/java/io/nexusrpc/client/GetResultResponse.java new file mode 100644 index 0000000..6585104 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/GetResultResponse.java @@ -0,0 +1,45 @@ +package io.nexusrpc.client; + +import io.nexusrpc.Link; +import java.util.List; + +public class GetResultResponse { + public static GetResultResponse.Builder newBuilder() { + return new GetResultResponse.Builder(); + } + + private final T result; + private final List links; + + private GetResultResponse(T result, List links) { + this.result = result; + this.links = links; + } + + public T getResult() { + return result; + } + + public List getLinks() { + return links; + } + + public static class Builder { + private T result; + private List links; + + public Builder setResult(T result) { + this.result = result; + return this; + } + + public Builder setLinks(List links) { + this.links = links; + return this; + } + + public GetResultResponse build() { + return new GetResultResponse<>(result, links); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/OperationHandle.java b/nexus-sdk/src/main/java/io/nexusrpc/client/OperationHandle.java new file mode 100644 index 0000000..3aa7647 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/OperationHandle.java @@ -0,0 +1,35 @@ +package io.nexusrpc.client; + +import io.nexusrpc.OperationInfo; +import java.util.concurrent.CompletableFuture; + +/** + * OperationHandle represents a handle to an operation that can be used to interact with the + * operation. + */ +public interface OperationHandle { + String getOperationName(); + + String getServiceName(); + + String getOperationToken(); + + OperationInfo getInfo(GetOperationInfoOptions options); + + void cancel(CancelOperationOptions options); + + T getResult(GetOperationResultOptions options); + + GetResultResponse getResultWithDetails(GetOperationResultOptions options); + + CompletableFuture getInfoAsync(GetOperationInfoOptions options); + + CompletableFuture cancelAsync(CancelOperationOptions options); + + CompletableFuture getResultAsync(GetOperationResultOptions options); + + CompletableFuture> getResultWithDetailsAsync( + GetOperationResultOptions options); + + // TODO Add no arg versions of the above methods that use default options. +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/ServiceClient.java b/nexus-sdk/src/main/java/io/nexusrpc/client/ServiceClient.java new file mode 100644 index 0000000..9751fda --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/ServiceClient.java @@ -0,0 +1,65 @@ +package io.nexusrpc.client; + +import java.util.function.BiFunction; + +public interface ServiceClient { + /** + * Executes an operation on the Nexus service with the provided input. This method is synchronous + * and returns the result directly. + * + * @param operation The operation method to execute, represented as a BiFunction. + * @param input The input to the operation. + * @return The result of the operation. + */ + R executeOperation(BiFunction operation, U input); + + /** + * Executes an operation on the Nexus service with the provided input. This method is synchronous + * and returns the result directly. + * + * @param operation The operation method to execute, represented as a BiFunction. + * @param input The input to the operation. + * @param options for execute operations + * @return The result of the operation. + */ + R executeOperation( + BiFunction operation, U input, ExecuteOperationOptions options); + + /** + * Starts an operation on the Nexus service with the provided input. + * + * @param operation The operation method to start, represented as a BiFunction. + * @param input The input to the operation. + */ + StartOperationResult startOperation(BiFunction operation, U input); + + /** + * Starts an operation on the Nexus service with the provided input. + * + * @param operation The operation method to start, represented as a BiFunction. + * @param input The input to the operation. + * @param options for start operations + */ + StartOperationResult startOperation( + BiFunction operation, U input, StartOperationOptions options); + + /** + * Gets a handle to an asynchronous operation. + * + *

Note: This does not perform validation that the token is valid. + * + * @param operation name of the operation. + * @param token operation token. + */ + OperationHandle newHandle(String operation, String token); + + /** + * Gets a handle to an asynchronous operation. + * + *

Note: This does not perform validation that the token is valid. + * + * @param operation operation method. + * @param token operation token. + */ + OperationHandle newHandle(BiFunction operation, String token); +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationOptions.java b/nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationOptions.java new file mode 100644 index 0000000..f57d973 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationOptions.java @@ -0,0 +1,89 @@ +package io.nexusrpc.client; + +import io.nexusrpc.Link; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class StartOperationOptions { + private final Map headers; + private final String callbackURL; + private final Map callbackHeaders; + private final String requestId; + private final List inboundLinks; + + public StartOperationOptions( + Map headers, + String callbackURL, + Map callbackHeaders, + String requestId, + List inboundLinks) { + this.headers = headers; + this.callbackURL = callbackURL; + this.callbackHeaders = callbackHeaders; + this.requestId = requestId; + this.inboundLinks = inboundLinks; + } + + public Map getHeaders() { + return headers; + } + + public String getCallbackURL() { + return callbackURL; + } + + public Map getCallbackHeaders() { + return callbackHeaders; + } + + public String getRequestId() { + return requestId; + } + + public List getInboundLinks() { + return inboundLinks; + } + + public static class Builder { + private final SortedMap headers; + private String callbackURL; + private SortedMap callbackHeaders; + private String requestId; + private List inboundLinks; + + public Builder() { + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + callbackHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + } + + public Map getHeaders() { + return headers; + } + + public Builder setCallbackURL(String callbackURL) { + this.callbackURL = callbackURL; + return this; + } + + public Map getCallbackHeaders() { + return callbackHeaders; + } + + public Builder setRequestId(String requestId) { + this.requestId = requestId; + return this; + } + + public Builder setInboundLinks(List inboundLinks) { + this.inboundLinks = inboundLinks; + return this; + } + + public StartOperationOptions build() { + return new StartOperationOptions( + headers, callbackURL, callbackHeaders, requestId, inboundLinks); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationResult.java b/nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationResult.java new file mode 100644 index 0000000..5a4a76e --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationResult.java @@ -0,0 +1,21 @@ +package io.nexusrpc.client; + +import io.nexusrpc.Link; +import java.util.List; +import org.jspecify.annotations.Nullable; + +// TODO this can also be an interface with two implementations: one for synchronous and one for +// asynchronous operations. +public class StartOperationResult { + @Nullable T getResult() { + return null; + } + + @Nullable OperationHandle getPendingOperationHandle() { + return null; + } + + List getLinks() { + return null; + } +} From 3eee40aa66fcc89639a91f1c0936e00c75cca59a Mon Sep 17 00:00:00 2001 From: Quinn Klassen Date: Tue, 22 Jul 2025 10:24:29 -0700 Subject: [PATCH 2/2] Add transport --- .../io/nexusrpc/client/OperationHandle.java | 121 ++++++++++++++++-- .../io/nexusrpc/client/ServiceClient.java | 86 ++++++++++++- .../client/StartOperationOptions.java | 6 +- .../transport/CancelOperationOptions.java | 40 ++++++ .../transport/CancelOperationResponse.java | 3 + .../transport/GetOperationInfoOptions.java | 40 ++++++ .../transport/GetOperationInfoResponse.java | 35 +++++ .../transport/GetOperationResultOptions.java | 59 +++++++++ .../transport/GetOperationResultResponse.java | 45 +++++++ .../transport/StartOperationOptions.java | 94 ++++++++++++++ .../transport/StartOperationResponse.java | 57 +++++++++ .../nexusrpc/client/transport/Transport.java | 50 ++++++++ 12 files changed, 616 insertions(+), 20 deletions(-) create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/transport/CancelOperationOptions.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/transport/CancelOperationResponse.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationInfoOptions.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationInfoResponse.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationResultOptions.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationResultResponse.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/transport/StartOperationOptions.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/transport/StartOperationResponse.java create mode 100644 nexus-sdk/src/main/java/io/nexusrpc/client/transport/Transport.java diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/OperationHandle.java b/nexus-sdk/src/main/java/io/nexusrpc/client/OperationHandle.java index 3aa7647..d7beebd 100644 --- a/nexus-sdk/src/main/java/io/nexusrpc/client/OperationHandle.java +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/OperationHandle.java @@ -1,35 +1,132 @@ package io.nexusrpc.client; import io.nexusrpc.OperationInfo; +import io.nexusrpc.client.transport.GetOperationInfoResponse; +import io.nexusrpc.client.transport.GetOperationResultResponse; +import io.nexusrpc.client.transport.Transport; import java.util.concurrent.CompletableFuture; /** * OperationHandle represents a handle to an operation that can be used to interact with the * operation. */ -public interface OperationHandle { - String getOperationName(); +public class OperationHandle { + private final String operation; + private final String service; + private final String operationToken; + private final Transport transport; - String getServiceName(); + public OperationHandle( + String operation, String service, String operationToken, Transport transport) { + this.operation = operation; + this.service = service; + this.operationToken = operationToken; + this.transport = transport; + } - String getOperationToken(); + public String getOperation() { + return operation; + } - OperationInfo getInfo(GetOperationInfoOptions options); + public String getService() { + return service; + } - void cancel(CancelOperationOptions options); + String getOperationToken() { + return operationToken; + } - T getResult(GetOperationResultOptions options); + OperationInfo getInfo(GetOperationInfoOptions options) { + // TODO: translate options to transport options if necessary + return transport + .getOperationInfo( + operation, + service, + operationToken, + io.nexusrpc.client.transport.GetOperationInfoOptions.newBuilder().build()) + .getOperationInfo(); + } - GetResultResponse getResultWithDetails(GetOperationResultOptions options); + void cancel(CancelOperationOptions options) { + // TODO: translate options to transport options if necessary + transport.cancelOperation( + operation, + service, + operationToken, + io.nexusrpc.client.transport.CancelOperationOptions.newBuilder().build()); + } - CompletableFuture getInfoAsync(GetOperationInfoOptions options); + T getResult(GetOperationResultOptions options) { + // TODO: translate options to transport options if necessary + return (T) + transport + .getOperationResult( + operation, + service, + operationToken, + io.nexusrpc.client.transport.GetOperationResultOptions.newBuilder().build()) + .getResult(); + } - CompletableFuture cancelAsync(CancelOperationOptions options); + GetResultResponse getResultWithDetails(GetOperationResultOptions options) { + // TODO: translate options to transport options if necessary + GetOperationResultResponse response = + transport.getOperationResult( + operation, + service, + operationToken, + io.nexusrpc.client.transport.GetOperationResultOptions.newBuilder().build()); + return GetResultResponse.newBuilder() + .setResult(response) + .setLinks(response.getLinks()) + .build(); + } - CompletableFuture getResultAsync(GetOperationResultOptions options); + CompletableFuture getInfoAsync(GetOperationInfoOptions options) { + return transport + .getOperationInfoAsync( + operation, + service, + operationToken, + io.nexusrpc.client.transport.GetOperationInfoOptions.newBuilder().build()) + .thenApply(GetOperationInfoResponse::getOperationInfo); + } + + CompletableFuture cancelAsync(CancelOperationOptions options) { + return transport + .cancelOperationAsync( + operation, + service, + operationToken, + io.nexusrpc.client.transport.CancelOperationOptions.newBuilder().build()) + .thenApply(response -> null); + } + + CompletableFuture getResultAsync(GetOperationResultOptions options) { + return transport + .getOperationResultAsync( + operation, + service, + operationToken, + io.nexusrpc.client.transport.GetOperationResultOptions.newBuilder().build()) + .thenApply(response -> (T) response.getResult()); + } CompletableFuture> getResultWithDetailsAsync( - GetOperationResultOptions options); + GetOperationResultOptions options) { + return transport + .getOperationResultAsync( + operation, + service, + operationToken, + io.nexusrpc.client.transport.GetOperationResultOptions.newBuilder().build()) + .thenApply( + response -> + GetResultResponse.newBuilder() + .setResult(response) + .setLinks(response.getLinks()) + .build()); + } // TODO Add no arg versions of the above methods that use default options. } diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/ServiceClient.java b/nexus-sdk/src/main/java/io/nexusrpc/client/ServiceClient.java index 9751fda..2a9140f 100644 --- a/nexus-sdk/src/main/java/io/nexusrpc/client/ServiceClient.java +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/ServiceClient.java @@ -1,8 +1,20 @@ package io.nexusrpc.client; +import io.nexusrpc.client.transport.GetOperationResultResponse; +import io.nexusrpc.client.transport.StartOperationResponse; +import io.nexusrpc.client.transport.Transport; import java.util.function.BiFunction; -public interface ServiceClient { +public class ServiceClient { + private final String service; + private final Transport transport; + + // TODO maybe use the builder pattern for consistency + public ServiceClient(String service, Transport transport) { + this.service = service; + this.transport = transport; + } + /** * Executes an operation on the Nexus service with the provided input. This method is synchronous * and returns the result directly. @@ -11,7 +23,9 @@ public interface ServiceClient { * @param input The input to the operation. * @return The result of the operation. */ - R executeOperation(BiFunction operation, U input); + R executeOperation(BiFunction operation, U input) { + throw new UnsupportedOperationException("Not implemented yet"); + } /** * Executes an operation on the Nexus service with the provided input. This method is synchronous @@ -23,7 +37,9 @@ public interface ServiceClient { * @return The result of the operation. */ R executeOperation( - BiFunction operation, U input, ExecuteOperationOptions options); + BiFunction operation, U input, ExecuteOperationOptions options) { + throw new UnsupportedOperationException("Not implemented yet"); + } /** * Starts an operation on the Nexus service with the provided input. @@ -31,7 +47,9 @@ R executeOperation( * @param operation The operation method to start, represented as a BiFunction. * @param input The input to the operation. */ - StartOperationResult startOperation(BiFunction operation, U input); + StartOperationResult startOperation(BiFunction operation, U input) { + throw new UnsupportedOperationException("Not implemented yet"); + } /** * Starts an operation on the Nexus service with the provided input. @@ -41,7 +59,57 @@ R executeOperation( * @param options for start operations */ StartOperationResult startOperation( - BiFunction operation, U input, StartOperationOptions options); + BiFunction operation, U input, StartOperationOptions options) { + throw new UnsupportedOperationException("Not implemented yet"); + } + + /** + * Starts an operation on the Nexus service with the provided input. + * + * @param operation The operation name to start. + * @param input The input to the operation. + * @param options for start operations + */ + StartOperationResult startOperation( + String operation, U input, StartOperationOptions options) { + // TODO translate options to transport options + StartOperationResponse response = + transport.startOperation( + operation, + service, + io.nexusrpc.client.transport.StartOperationOptions.newBuilder().build()); + // TODO handle response and convert to StartOperationResult + return new StartOperationResult<>(); + } + + /** + * Execute an operation on the Nexus service with the provided input. + * + * @param operation The operation name to start. + * @param input The input to the operation. + * @param options for start operations + */ + StartOperationResult executeOperation( + String operation, U input, ExecuteOperationOptions options) { + // TODO translate options to transport options + StartOperationResponse response = + transport.startOperation( + operation, + service, + io.nexusrpc.client.transport.StartOperationOptions.newBuilder().build()); + if (response.getSyncResult() != null) { + // If the operation is synchronous, return the result directly + return new StartOperationResult<>(); + } + // TODO handle response and convert to GetOperationResultOptions + GetOperationResultResponse result = + transport.getOperationResult( + operation, + service, + response.getAsyncOperationToken(), + io.nexusrpc.client.transport.GetOperationResultOptions.newBuilder().build()); + return new StartOperationResult<>(); + } /** * Gets a handle to an asynchronous operation. @@ -51,7 +119,9 @@ StartOperationResult startOperation( * @param operation name of the operation. * @param token operation token. */ - OperationHandle newHandle(String operation, String token); + OperationHandle newHandle(String operation, String token) { + return new OperationHandle<>(operation, service, token, transport); + } /** * Gets a handle to an asynchronous operation. @@ -61,5 +131,7 @@ StartOperationResult startOperation( * @param operation operation method. * @param token operation token. */ - OperationHandle newHandle(BiFunction operation, String token); + OperationHandle newHandle(BiFunction operation, String token) { + throw new UnsupportedOperationException("Not implemented yet"); + } } diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationOptions.java b/nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationOptions.java index f57d973..18d0ee6 100644 --- a/nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationOptions.java +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/StartOperationOptions.java @@ -7,13 +7,17 @@ import java.util.TreeMap; public class StartOperationOptions { + public static Builder newBuilder() { + return new Builder(); + } + private final Map headers; private final String callbackURL; private final Map callbackHeaders; private final String requestId; private final List inboundLinks; - public StartOperationOptions( + private StartOperationOptions( Map headers, String callbackURL, Map callbackHeaders, diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/transport/CancelOperationOptions.java b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/CancelOperationOptions.java new file mode 100644 index 0000000..cd94779 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/CancelOperationOptions.java @@ -0,0 +1,40 @@ +package io.nexusrpc.client.transport; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class CancelOperationOptions { + /** Create a builder for CancelOperationOptions. */ + public static Builder newBuilder() { + return new Builder(); + } + + private final SortedMap headers; + + private CancelOperationOptions(SortedMap headers) { + this.headers = headers; + } + + /** Headers. The returned map operates without regard to case. */ + public Map getHeaders() { + return headers; + } + + public static class Builder { + private final SortedMap headers; + + private Builder() { + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + } + + /** Get headers to mutate. */ + public Map getHeaders() { + return headers; + } + + public CancelOperationOptions build() { + return new CancelOperationOptions(headers); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/transport/CancelOperationResponse.java b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/CancelOperationResponse.java new file mode 100644 index 0000000..c35a944 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/CancelOperationResponse.java @@ -0,0 +1,3 @@ +package io.nexusrpc.client.transport; + +public class CancelOperationResponse {} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationInfoOptions.java b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationInfoOptions.java new file mode 100644 index 0000000..9837b10 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationInfoOptions.java @@ -0,0 +1,40 @@ +package io.nexusrpc.client.transport; + +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class GetOperationInfoOptions { + /** Create a builder for GetOperationInfoOptions. */ + public static Builder newBuilder() { + return new Builder(); + } + + private final SortedMap headers; + + private GetOperationInfoOptions(SortedMap headers) { + this.headers = headers; + } + + /** Headers. The returned map operates without regard to case. */ + public Map getHeaders() { + return headers; + } + + public static class Builder { + private final SortedMap headers; + + private Builder() { + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + } + + /** Get headers to mutate. */ + public Map getHeaders() { + return headers; + } + + public GetOperationInfoOptions build() { + return new GetOperationInfoOptions(headers); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationInfoResponse.java b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationInfoResponse.java new file mode 100644 index 0000000..717ec23 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationInfoResponse.java @@ -0,0 +1,35 @@ +package io.nexusrpc.client.transport; + +import io.nexusrpc.OperationInfo; + +public class GetOperationInfoResponse { + /** Create a builder for GetOperationInfoResponse. */ + public static Builder newBuilder() { + return new Builder(); + } + + private final OperationInfo operationInfo; + + private GetOperationInfoResponse(OperationInfo operationInfo) { + this.operationInfo = operationInfo; + } + + public OperationInfo getOperationInfo() { + return operationInfo; + } + + public static class Builder { + private OperationInfo operationInfo; + + private Builder() {} + + public Builder setOperationInfo(OperationInfo operationInfo) { + this.operationInfo = operationInfo; + return this; + } + + public GetOperationInfoResponse build() { + return new GetOperationInfoResponse(operationInfo); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationResultOptions.java b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationResultOptions.java new file mode 100644 index 0000000..46bd70d --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationResultOptions.java @@ -0,0 +1,59 @@ +package io.nexusrpc.client.transport; + +import java.time.Duration; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class GetOperationResultOptions { + /** Create a builder for GetOperationResultOptions. */ + public static Builder newBuilder() { + return new Builder(); + } + + private final Duration timeout; + private final SortedMap headers; + + private GetOperationResultOptions(Duration timeout, SortedMap headers) { + this.timeout = timeout; + this.headers = headers; + } + + /** Headers. The returned map operates without regard to case. */ + public Map getHeaders() { + return headers; + } + + public Duration getTimeout() { + return timeout; + } + + public static class Builder { + private final SortedMap headers; + private Duration timeout; + + private Builder() { + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + } + + /** Get headers to mutate. */ + public Map getHeaders() { + return headers; + } + + /** + * Set the timeout for the operation. + * + * @param timeout the duration to wait for the operation result + * @return this builder instance + */ + public Builder setTimeout(Duration timeout) { + this.timeout = timeout; + return this; + } + + public GetOperationResultOptions build() { + return new GetOperationResultOptions(timeout, headers); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationResultResponse.java b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationResultResponse.java new file mode 100644 index 0000000..77f3ce0 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/GetOperationResultResponse.java @@ -0,0 +1,45 @@ +package io.nexusrpc.client.transport; + +import io.nexusrpc.Link; +import java.util.List; + +public class GetOperationResultResponse { + public static GetOperationResultResponse.Builder newBuilder() { + return new GetOperationResultResponse.Builder(); + } + + private final Object result; + private final List links; + + private GetOperationResultResponse(Object result, List links) { + this.result = result; + this.links = links; + } + + public Object getResult() { + return result; + } + + public List getLinks() { + return links; + } + + public static class Builder { + private Object result; + private List links; + + public GetOperationResultResponse.Builder setResult(Object result) { + this.result = result; + return this; + } + + public GetOperationResultResponse.Builder setLinks(List links) { + this.links = links; + return this; + } + + public GetOperationResultResponse build() { + return new GetOperationResultResponse(result, links); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/transport/StartOperationOptions.java b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/StartOperationOptions.java new file mode 100644 index 0000000..e177cc0 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/StartOperationOptions.java @@ -0,0 +1,94 @@ +package io.nexusrpc.client.transport; + +import io.nexusrpc.Link; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class StartOperationOptions { + /** Create a builder for StartOperationOptions. */ + public static Builder newBuilder() { + return new Builder(); + } + + private final Map headers; + private final String callbackURL; + private final Map callbackHeaders; + private final String requestId; + private final List inboundLinks; + + private StartOperationOptions( + Map headers, + String callbackURL, + Map callbackHeaders, + String requestId, + List inboundLinks) { + this.headers = headers; + this.callbackURL = callbackURL; + this.callbackHeaders = callbackHeaders; + this.requestId = requestId; + this.inboundLinks = inboundLinks; + } + + public Map getHeaders() { + return headers; + } + + public String getCallbackURL() { + return callbackURL; + } + + public Map getCallbackHeaders() { + return callbackHeaders; + } + + public String getRequestId() { + return requestId; + } + + public List getInboundLinks() { + return inboundLinks; + } + + public static class Builder { + private final SortedMap headers; + private String callbackURL; + private SortedMap callbackHeaders; + private String requestId; + private List inboundLinks; + + public Builder() { + headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + callbackHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + } + + public Map getHeaders() { + return headers; + } + + public Builder setCallbackURL(String callbackURL) { + this.callbackURL = callbackURL; + return this; + } + + public Map getCallbackHeaders() { + return callbackHeaders; + } + + public Builder setRequestId(String requestId) { + this.requestId = requestId; + return this; + } + + public Builder setInboundLinks(List inboundLinks) { + this.inboundLinks = inboundLinks; + return this; + } + + public StartOperationOptions build() { + return new StartOperationOptions( + headers, callbackURL, callbackHeaders, requestId, inboundLinks); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/transport/StartOperationResponse.java b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/StartOperationResponse.java new file mode 100644 index 0000000..634e553 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/StartOperationResponse.java @@ -0,0 +1,57 @@ +package io.nexusrpc.client.transport; + +import io.nexusrpc.Link; +import java.util.List; + +public class StartOperationResponse { + public static Builder newBuilder() { + return new Builder(); + } + + private final Object syncResult; + private final List links; + private final String asyncOperationToken; + + private StartOperationResponse(Object syncResult, String asyncOperationToken, List links) { + this.syncResult = syncResult; + this.asyncOperationToken = asyncOperationToken; + this.links = links; + } + + public Object getSyncResult() { + return syncResult; + } + + public String getAsyncOperationToken() { + return asyncOperationToken; + } + + public List getLinks() { + return links; + } + + public static class Builder { + private Object syncResult; + private String asyncOperationToken; + private List links; + + public Builder setResult(Object syncResult) { + this.syncResult = syncResult; + return this; + } + + public Builder setAsyncOperationToken(String asyncOperationToken) { + this.asyncOperationToken = asyncOperationToken; + return this; + } + + public Builder setLinks(List links) { + this.links = links; + return this; + } + + public StartOperationResponse build() { + return new StartOperationResponse(syncResult, asyncOperationToken, links); + } + } +} diff --git a/nexus-sdk/src/main/java/io/nexusrpc/client/transport/Transport.java b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/Transport.java new file mode 100644 index 0000000..1f245a6 --- /dev/null +++ b/nexus-sdk/src/main/java/io/nexusrpc/client/transport/Transport.java @@ -0,0 +1,50 @@ +package io.nexusrpc.client.transport; + +import java.util.concurrent.CompletableFuture; + +public interface Transport { + StartOperationResponse startOperation( + String operationName, String serviceName, StartOperationOptions options); + + GetOperationResultResponse getOperationResult( + String operationName, + String serviceName, + String operationToken, + GetOperationResultOptions options); + + GetOperationInfoResponse getOperationInfo( + String operationName, + String serviceName, + String operationToken, + GetOperationInfoOptions options); + + CancelOperationResponse cancelOperation( + String operationName, + String serviceName, + String operationToken, + CancelOperationOptions options); + + CompletableFuture startOperationAsync( + String operationName, + String serviceName, + String operationToken, + StartOperationOptions options); + + CompletableFuture getOperationResultAsync( + String operationName, + String serviceName, + String operationToken, + GetOperationResultOptions options); + + CompletableFuture getOperationInfoAsync( + String operationName, + String serviceName, + String operationToken, + GetOperationInfoOptions options); + + CompletableFuture cancelOperationAsync( + String operationName, + String serviceName, + String operationToken, + CancelOperationOptions options); +}