com.fnproject.fn.runtime.flow.RemoteFlow Maven / Gradle / Ivy
/*
* Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved.
*
* 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.fnproject.fn.runtime.flow;
import com.fnproject.fn.api.Headers;
import com.fnproject.fn.api.flow.*;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
/**
* REST flows runtime
*
* This
*/
public final class RemoteFlow implements Flow, Serializable, FlowFutureSource {
private transient CompleterClient client;
private final FlowId flowId;
RemoteFlow(FlowId flowId) {
this.flowId = Objects.requireNonNull(flowId);
}
private CompleterClient getClient() {
if (client == null) {
client = FlowRuntimeGlobals.getCompleterClientFactory().getCompleterClient();
}
return client;
}
@Override
public FlowFuture createFlowFuture(CompletionId completionId) {
return new RemoteFlowFuture<>(completionId);
}
public FlowId getFlowId() {
return flowId;
}
class RemoteFlowFuture implements FlowFuture, Serializable {
private final CompletionId completionId;
RemoteFlowFuture(CompletionId completionId) {
this.completionId = Objects.requireNonNull(completionId, "completionId");
}
@Override
public FlowFuture thenApply(Flows.SerFunction fn) {
CompletionId newcid = getClient().thenApply(flowId, completionId, fn, CodeLocation.fromCallerLocation(1));
return new RemoteFlowFuture<>(newcid);
}
@Override
public FlowFuture thenCompose(Flows.SerFunction> fn) {
CompletionId newCid = getClient().thenCompose(flowId, completionId, fn, CodeLocation.fromCallerLocation(1));
return new RemoteFlowFuture<>(newCid);
}
@Override
public FlowFuture exceptionallyCompose(Flows.SerFunction> fn) {
return new RemoteFlowFuture<>(getClient().exceptionallyCompose(flowId, completionId, fn, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture whenComplete(Flows.SerBiConsumer fn) {
return new RemoteFlowFuture<>(getClient().whenComplete(flowId, completionId, fn, CodeLocation.fromCallerLocation(1)));
}
@Override
public boolean complete(T value) {
return getClient().complete(flowId, completionId, value, CodeLocation.fromCallerLocation(1));
}
@Override
public boolean completeExceptionally(Throwable throwable) {
return getClient().completeExceptionally(flowId, completionId, throwable, CodeLocation.fromCallerLocation(1));
}
@Override
public boolean cancel() {
return getClient().completeExceptionally(flowId, completionId, new CancellationException(), CodeLocation.fromCallerLocation(1));
}
@Override
public FlowFuture thenAccept(Flows.SerConsumer fn) {
return new RemoteFlowFuture<>(getClient().thenAccept(flowId, completionId, fn, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture acceptEither(FlowFuture extends T> alt, Flows.SerConsumer fn) {
return new RemoteFlowFuture<>(getClient().acceptEither(flowId, completionId, ((RemoteFlowFuture>) alt).completionId, fn, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture applyToEither(FlowFuture extends T> alt, Flows.SerFunction fn) {
return new RemoteFlowFuture<>(getClient().applyToEither(flowId, completionId, ((RemoteFlowFuture>) alt).completionId, fn, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture thenAcceptBoth(FlowFuture alt, Flows.SerBiConsumer fn) {
return new RemoteFlowFuture<>(getClient().thenAcceptBoth(flowId, completionId, ((RemoteFlowFuture>) alt).completionId, fn, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture thenRun(Flows.SerRunnable fn) {
return new RemoteFlowFuture<>(getClient().thenRun(flowId, completionId, fn, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture handle(Flows.SerBiFunction super T, Throwable, ? extends X> fn) {
return new RemoteFlowFuture<>(getClient().handle(flowId, completionId, fn, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture exceptionally(Flows.SerFunction fn) {
return new RemoteFlowFuture<>(getClient().exceptionally(flowId, completionId, fn, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture thenCombine(FlowFuture extends U> other, Flows.SerBiFunction super T, ? super U, ? extends X> fn) {
return new RemoteFlowFuture<>(getClient().thenCombine(flowId, completionId, fn, ((RemoteFlowFuture>) other).completionId, CodeLocation.fromCallerLocation(1)));
}
@Override
public T get() {
return (T) getClient().waitForCompletion(flowId, completionId, getClass().getClassLoader());
}
@Override
public T get(long timeout, TimeUnit unit) throws TimeoutException {
return (T) getClient().waitForCompletion(flowId, completionId, getClass().getClassLoader(), timeout, unit);
}
@Override
public T getNow(T valueIfAbsent) {
try {
return get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
return valueIfAbsent;
}
}
public String id() {
return completionId.getId();
}
}
@Override
public FlowFuture invokeFunction(String functionId, HttpMethod method, Headers headers, byte[] data) {
CompletionId cid = getClient().invokeFunction(flowId, functionId, data, method, headers, CodeLocation.fromCallerLocation(1));
return new RemoteFlowFuture<>(cid);
}
@Override
public FlowFuture invokeFunction(String functionId, HttpMethod method, Headers headers, U input, Class responseType) {
return JsonInvoke.invokeFunction(this, functionId, method, headers, input, responseType);
}
@Override
public FlowFuture invokeFunction(String functionId, HttpMethod method, Headers headers, U input) {
return JsonInvoke.invokeFunction(this, functionId, method, headers, input);
}
@Override
public FlowFuture supply(Flows.SerCallable c) {
CompletionId cid = getClient().supply(flowId, c, CodeLocation.fromCallerLocation(1));
return new RemoteFlowFuture<>(cid);
}
@Override
public FlowFuture supply(Flows.SerRunnable runnable) {
CompletionId cid = getClient().supply(flowId, runnable, CodeLocation.fromCallerLocation(1));
return new RemoteFlowFuture<>(cid);
}
@Override
public FlowFuture delay(long i, TimeUnit tu) {
if (i < 0) {
throw new IllegalArgumentException("Delay value must be non-negative");
}
CompletionId cid = getClient().delay(flowId, tu.toMillis(i), CodeLocation.fromCallerLocation(1));
return new RemoteFlowFuture<>(cid);
}
@Override
public FlowFuture completedValue(T value) {
return new RemoteFlowFuture<>(getClient().completedValue(flowId, true, value, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture failedFuture(Throwable ex) {
return new RemoteFlowFuture<>(getClient().completedValue(flowId, false, ex, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture createFlowFuture() {
return new RemoteFlowFuture<>(getClient().createCompletion(flowId, CodeLocation.fromCallerLocation(1)));
}
@Override
public FlowFuture allOf(FlowFuture>... flowFutures) {
if (flowFutures.length == 0) {
throw new IllegalArgumentException("at least one future must be specified");
}
List cids = Arrays.stream(flowFutures).map((cf) -> ((RemoteFlowFuture>) cf).completionId).collect(Collectors.toList());
CompletionId cid = getClient().allOf(flowId, cids, CodeLocation.fromCallerLocation(1));
return new RemoteFlowFuture<>(cid);
}
@Override
public FlowFuture