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

com.hazelcast.spi.impl.DeserializingCompletableFuture Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2008-2024, Hazelcast, Inc. 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.hazelcast.spi.impl;

import com.hazelcast.internal.serialization.InternalSerializationService;
import com.hazelcast.internal.serialization.SerializationService;
import com.hazelcast.internal.serialization.Data;
import com.hazelcast.internal.util.ConcurrencyUtil;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Decorates {@link InternalCompletableFuture} to supply:
 * 
    *
  • optional value deserialization
  • *
  • custom default async executor
  • *
*/ @SuppressWarnings("checkstyle:methodcount") public class DeserializingCompletableFuture extends InternalCompletableFuture { /** * Reference to serialization service; can be {@code null} when {@code deserialize} is {@code false} */ private final InternalSerializationService serializationService; /** * Default executor for execution of callbacks registered with async methods without * explicit {@link Executor} argument (eg. {@link #whenCompleteAsync(BiConsumer)}. */ private final Executor defaultAsyncExecutor; /** * When {@code true}, a completion value of type {@link Data} will be deserialized * before returned from one of the blocking results getter methods ({@link #get()}, {@link #join()} etc.) * or before passed as argument to callbacks such as {@link #thenAccept(Consumer)}. */ private final boolean deserialize; public DeserializingCompletableFuture() { this(null, ConcurrencyUtil.getDefaultAsyncExecutor(), false); } public DeserializingCompletableFuture(Executor defaultAsyncExecutor) { this(null, defaultAsyncExecutor, false); } public DeserializingCompletableFuture(SerializationService serializationService, boolean deserialize) { this(serializationService, ConcurrencyUtil.getDefaultAsyncExecutor(), deserialize); } public DeserializingCompletableFuture(SerializationService serializationService, Executor defaultAsyncExecutor, boolean deserialize) { this.serializationService = (InternalSerializationService) serializationService; this.defaultAsyncExecutor = defaultAsyncExecutor; this.deserialize = deserialize; } @Override public V get() throws InterruptedException, ExecutionException { return resolve(super.get()); } @Override public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return resolve(super.get(timeout, unit)); } @Override public V getNow(V valueIfAbsent) { V value = super.getNow(valueIfAbsent); return (deserialize && value instanceof Data) ? serializationService.toObject(value) : value; } @Override public V join() { return resolve(super.join()); } @Override public V joinInternal() { return resolve(super.joinInternal()); } @Override public CompletableFuture thenApply(Function fn) { return super.thenApply(new DeserializingFunction<>(fn)); } @Override public CompletableFuture thenApplyAsync(Function fn) { return super.thenApplyAsync(new DeserializingFunction<>(fn), defaultAsyncExecutor); } @Override public CompletableFuture thenApplyAsync(Function fn, Executor executor) { return super.thenApplyAsync(new DeserializingFunction<>(fn), executor); } @Override public CompletableFuture thenAccept(Consumer action) { return super.thenAccept(new DeserializingConsumer<>(action)); } @Override public CompletableFuture thenAcceptAsync(Consumer action) { return super.thenAcceptAsync(new DeserializingConsumer<>(action), defaultAsyncExecutor); } @Override public CompletableFuture thenAcceptAsync(Consumer action, Executor executor) { return super.thenAcceptAsync(new DeserializingConsumer<>(action), executor); } @Override public CompletableFuture thenRun(Runnable action) { return super.thenRun(action); } @Override public CompletableFuture thenRunAsync(Runnable action) { return super.thenRunAsync(action, defaultAsyncExecutor); } @Override public CompletableFuture thenRunAsync(Runnable action, Executor executor) { return super.thenRunAsync(action, executor); } @Override public CompletableFuture thenCombine(CompletionStage other, BiFunction fn) { return super.thenCombine(other, new DeserializingBiFunction<>(fn)); } @Override public CompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn) { return super.thenCombineAsync(other, new DeserializingBiFunction<>(fn), defaultAsyncExecutor); } @Override public CompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn, Executor executor) { return super.thenCombineAsync(other, new DeserializingBiFunction<>(fn), executor); } @Override public CompletableFuture thenAcceptBoth(CompletionStage other, BiConsumer action) { return super.thenAcceptBoth(other, new DeserializingBiConsumer<>(action)); } @Override public CompletableFuture thenAcceptBothAsync(CompletionStage other, BiConsumer action) { return super.thenAcceptBothAsync(other, new DeserializingBiConsumer<>(action), defaultAsyncExecutor); } @Override public CompletableFuture thenAcceptBothAsync(CompletionStage other, BiConsumer action, Executor executor) { return super.thenAcceptBothAsync(other, new DeserializingBiConsumer<>(action), executor); } @Override public CompletableFuture runAfterBoth(CompletionStage other, Runnable action) { return super.runAfterBoth(other, action); } @Override public CompletableFuture runAfterBothAsync(CompletionStage other, Runnable action) { return super.runAfterBothAsync(other, action, defaultAsyncExecutor); } @Override public CompletableFuture runAfterBothAsync(CompletionStage other, Runnable action, Executor executor) { return super.runAfterBothAsync(other, action, executor); } @Override public CompletableFuture applyToEither(CompletionStage other, Function fn) { return super.applyToEither(other, new DeserializingFunction<>(fn)); } @Override public CompletableFuture applyToEitherAsync(CompletionStage other, Function fn) { return super.applyToEitherAsync(other, new DeserializingFunction<>(fn), defaultAsyncExecutor); } @Override public CompletableFuture applyToEitherAsync(CompletionStage other, Function fn, Executor executor) { return super.applyToEitherAsync(other, new DeserializingFunction<>(fn), executor); } @Override public CompletableFuture acceptEither(CompletionStage other, Consumer action) { return super.acceptEither(other, new DeserializingConsumer<>(action)); } @Override public CompletableFuture acceptEitherAsync(CompletionStage other, Consumer action) { return super.acceptEitherAsync(other, new DeserializingConsumer<>(action), defaultAsyncExecutor); } @Override public CompletableFuture acceptEitherAsync(CompletionStage other, Consumer action, Executor executor) { return super.acceptEitherAsync(other, new DeserializingConsumer<>(action), executor); } @Override public CompletableFuture runAfterEither(CompletionStage other, Runnable action) { return super.runAfterEither(other, action); } @Override public CompletableFuture runAfterEitherAsync(CompletionStage other, Runnable action) { return super.runAfterEitherAsync(other, action, defaultAsyncExecutor); } @Override public CompletableFuture runAfterEitherAsync(CompletionStage other, Runnable action, Executor executor) { return super.runAfterEitherAsync(other, action, executor); } @Override public CompletableFuture thenCompose(Function> fn) { return super.thenCompose(new DeserializingFunction<>(fn)); } @Override public CompletableFuture thenComposeAsync(Function> fn) { return super.thenComposeAsync(new DeserializingFunction<>(fn), defaultAsyncExecutor); } @Override public CompletableFuture thenComposeAsync(Function> fn, Executor executor) { return super.thenComposeAsync(new DeserializingFunction<>(fn), executor); } @Override public CompletableFuture whenComplete(BiConsumer action) { if (!deserialize) { return super.whenComplete(new DeserializingBiConsumer<>(action)); } else { return new DelegatingCompletableFuture<>(serializationService, super.whenComplete(new DeserializingBiConsumer<>(action))); } } @Override public CompletableFuture whenCompleteAsync(BiConsumer action) { if (!deserialize) { return super.whenCompleteAsync(new DeserializingBiConsumer<>(action), defaultAsyncExecutor); } else { return new DelegatingCompletableFuture<>(serializationService, super.whenCompleteAsync(new DeserializingBiConsumer<>(action) , defaultAsyncExecutor)); } } @Override public CompletableFuture whenCompleteAsync(BiConsumer action, Executor executor) { if (!deserialize) { return super.whenCompleteAsync(new DeserializingBiConsumer<>(action), executor); } else { return new DelegatingCompletableFuture<>(serializationService, super.whenCompleteAsync(new DeserializingBiConsumer<>(action), executor)); } } @Override public CompletableFuture handle(BiFunction fn) { return super.handle(new DeserializingBiFunction<>(fn)); } @Override public CompletableFuture handleAsync(BiFunction fn) { return super.handleAsync(new DeserializingBiFunction<>(fn), defaultAsyncExecutor); } @Override public CompletableFuture handleAsync(BiFunction fn, Executor executor) { return super.handleAsync(new DeserializingBiFunction<>(fn), executor); } @Override public CompletableFuture exceptionally(Function fn) { if (!deserialize) { return super.exceptionally(fn); } else { return new DelegatingCompletableFuture<>(serializationService, super.exceptionally(fn)); } } private V resolve(Object object) { if (deserialize && object instanceof Data data) { // we need to deserialize. object = serializationService.toObject(data); //todo do we need to call dispose data here serializationService.disposeData(data); } return (V) object; } class DeserializingFunction implements Function { private final Function delegate; DeserializingFunction(Function delegate) { if (delegate == null) { throw new NullPointerException(); } this.delegate = delegate; } @Override public R apply(E e) { return delegate.apply(deserialize ? serializationService.toObject(e) : e); } } class DeserializingConsumer implements Consumer { private final Consumer delegate; DeserializingConsumer(Consumer delegate) { if (delegate == null) { throw new NullPointerException(); } this.delegate = delegate; } @Override public void accept(E e) { delegate.accept(deserialize ? serializationService.toObject(e) : e); } } class DeserializingBiFunction implements BiFunction { private final BiFunction delegate; DeserializingBiFunction(BiFunction delegate) { if (delegate == null) { throw new NullPointerException(); } this.delegate = delegate; } @Override public R apply(T t, U u) { return delegate.apply(deserialize ? serializationService.toObject(t) : t, deserialize ? serializationService.toObject(u) : u); } } class DeserializingBiConsumer implements BiConsumer { private final BiConsumer delegate; DeserializingBiConsumer(BiConsumer delegate) { if (delegate == null) { throw new NullPointerException(); } this.delegate = delegate; } @Override public void accept(T t, U u) { delegate.accept(deserialize ? serializationService.toObject(t) : t, deserialize ? serializationService.toObject(u) : u); } } }