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

com.vmware.operations.OperationSyncBase Maven / Gradle / Ivy

There is a newer version: 1.2.1
Show newest version
/*
 * Copyright (c) 2015-2018 VMware, Inc. All Rights Reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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.vmware.operations;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;

/**
 * Abstract base class for implementing operations that are implemented as
 * synchronous functions.
 *
 * This base class implements the asynchronous versions of execute, revert, and cleanup
 * in a standard way.
 */
public abstract class OperationSyncBase extends OperationBase {
    private final ExecutorService executorService;

    /**
     * Constructor.
     */
    protected OperationSyncBase() {
        super();
        this.executorService = Operations.getExecutorService();
    }

    /**
     * Constructor.
     * @param executorService the executor service to use when performing asynchronous
     *                        calls for this operation.
     */
    protected OperationSyncBase(ExecutorService executorService) {
        super();
        this.executorService = executorService;
    }

    @Override
    public final void execute() throws Throwable {
        executeImpl();

        // Unwrap the async exceptions
        try {
            validateExecution(executorService).get();
        } catch (ExecutionException ex) {
            // Unwrap the exception if possible
            Throwable cause = ex.getCause();
            if (cause != null) {
                throw cause;
            } else {
                throw ex;
            }
        }
    }

    @Override
    public final CompletableFuture executeAsync() {
        CompletableFuture executionResult = new CompletableFuture<>();
        try {
            executorService.execute(() -> {
                try {
                    executeImpl();
                    executionResult.complete(null);
                } catch (Throwable th) {
                    executionResult.completeExceptionally(th);
                }
            });
        } catch (Throwable th) {
            executionResult.completeExceptionally(th);
        }

        // Compose the validators onto the execution result
        return executionResult.thenComposeAsync(
                (unused) -> validateExecution(executorService), executorService);
    }

    @Override
    public final void revert() throws Throwable {
        revertImpl();

        // Unwrap the async exceptions
        try {
            validateRevert(executorService).get();
        } catch (ExecutionException ex) {
            // Unwrap the exception if possible
            Throwable cause = ex.getCause();
            if (cause != null) {
                throw cause;
            } else {
                throw ex;
            }
        }
    }

    @Override
    public final CompletableFuture revertAsync() {
        CompletableFuture revertResult = new CompletableFuture<>();
        try {
            executorService.execute(() -> {
                try {
                    revertImpl();
                    revertResult.complete(null);
                } catch (Throwable th) {
                    revertResult.completeExceptionally(th);
                }
            });
        } catch (Throwable th) {
            revertResult.completeExceptionally(th);
        }

        // Compose the validators onto the revert result
        return revertResult.thenComposeAsync(
                (unused) -> validateRevert(executorService), executorService);
    }

    @Override
    public void cleanup() {
        try {
            if (isExecuted()) {
                revert();
            }
        } catch (Throwable throwable) {
            // Catch failures, and suppress them during cleanup
            handleCleanupException(throwable);
        }

        // If revert failed, then it could have been the operation or the
        // validators that threw the error.  Ensure the validators
        // are cleaned up before leaving.

        try {
            validateCleanup(executorService).get();
        } catch (Throwable throwable) {
            // Catch failures, and suppress them during cleanup
            handleCleanupException(throwable);
        }
    }

    @Override
    public CompletableFuture cleanupAsync() {
        CompletableFuture result = new CompletableFuture<>();
        try {
            executorService.execute(() -> {
                try {
                    cleanup();
                    result.complete(null);
                } catch (Throwable th) {
                    result.completeExceptionally(th);
                }
            });
        } catch (Throwable th) {
            result.completeExceptionally(th);
        }
        return result;
    }

    @Override
    public void close() {
        cleanup();
    }

    /**
     * Synchronous implementation of the operation.
     * @throws Exception if the operation cannot be completed
     */
    public abstract void executeImpl() throws Throwable;

    /**
     * Synchronous revert implementation of the operation.
     * @throws Exception if the operation cannot be reverted
     */
    public abstract void revertImpl() throws Throwable;

    @Override
    public abstract String toString();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy