All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 alt, Flows.SerConsumer fn) { return new RemoteFlowFuture<>(getClient().acceptEither(flowId, completionId, ((RemoteFlowFuture) alt).completionId, fn, CodeLocation.fromCallerLocation(1))); } @Override public FlowFuture applyToEither(FlowFuture 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 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 other, Flows.SerBiFunction 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 anyOf(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().anyOf(flowId, cids, CodeLocation.fromCallerLocation(1)); return new RemoteFlowFuture<>(cid); } @Override public Flow addTerminationHook(Flows.SerConsumer hook) { getClient().addTerminationHook(flowId, hook, CodeLocation.fromCallerLocation(1)); return this; } }