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

com.vmware.photon.controller.model.adapters.awsadapter.util.AWSDeferredResultAsyncHandler Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2015-2016 VMware, 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.vmware.photon.controller.model.adapters.awsadapter.util;

import com.amazonaws.AmazonWebServiceRequest;

import com.vmware.xenon.common.DeferredResult;
import com.vmware.xenon.common.StatelessService;
import com.vmware.xenon.common.Utils;

/**
 * {@link AWSAsyncHandler} that bridges to {@link DeferredResult}. The benefit is that async
 * handling across Xenon, Azure, AWS, etc. is unified based on {@code DeferredResult}.
 */
public class AWSDeferredResultAsyncHandler
        extends AWSAsyncHandler {

    /**
     * Return this instance by {@link #consumeError(Exception)} to indicate that the descendant has
     * recovered from exception.
     */
    protected static final Exception RECOVERED = null;

    /**
     * The DeferredResult instance used to track this async callback.
     */
    private final DeferredResult deferredResult = new DeferredResult<>();

    /**
     * Return this async callback as DeferredResult instance.
     */
    public DeferredResult toDeferredResult() {
        return this.deferredResult;
    }

    /**
     * Hook that might be implemented by descendants to handle successful AWS call.
     * By default the AWS result is returned as {@link DeferredResult}.
     */
    protected DeferredResult consumeSuccess(REQ request, RES result) {
        return DeferredResult.completed(result);
    }

    /**
     * Hook that might be implemented by descendants to handle failed AWS call.
     *
     * @return The exception to propagate or {@link #RECOVERED} to indicate the handler has
     *         recovered from the exception.
     */
    protected Exception consumeError(Exception exception) {
        return exception;
    }

    protected final String message;

    /**
     * Constructs {@link AWSDeferredResultAsyncHandler}.
     *
     * @param service The service that is talking with AWS.
     * @param message Informational message that describes the Service to AWS interaction.
     */
    public AWSDeferredResultAsyncHandler(StatelessService service, String message) {
        super(service);
        this.message = message;
    }

    @Override
    protected final void handleError(Exception exc) {
        final Throwable consumedError;
        try {
            // First delegate to descendants to process exc
            consumedError = consumeError(exc);
        } catch (Throwable t) {
            if (this.service != null) {
                this.service.logWarning(() -> String.format("%s: FAILED with %s",
                        this.message, Utils.toString(t)));
            }
            toDeferredResult().fail(t);
            return;
        }

        // Then propagate through the DeferredResult
        if (consumedError == RECOVERED) {
            // The code has recovered from exception
            if (this.service != null) {
                this.service.logFine(() -> String.format("%s: SUCCESS with error. Details: %s",
                        this.message, Utils.toString(exc)));
            }
            toDeferredResult().complete(null);
        } else {
            if (this.service != null) {
                this.service.logWarning(() -> String.format("%s: FAILED with %s",
                        this.message, Utils.toString(consumedError)));
            }
            toDeferredResult().fail(consumedError);
        }
    }

    @Override
    protected final void handleSuccess(REQ request, RES result) {
        final DeferredResult consumeSuccess;
        if (this.service != null) {
            this.service.logFine(() -> this.message + ": SUCCESS");
        }
        try {
            // First delegate to descendants to process result
            consumeSuccess = consumeSuccess(request, result);
        } catch (Throwable t) {
            toDeferredResult().fail(t);
            return;
        }

        // Then propagate through the DeferredResult
        consumeSuccess.whenComplete((body, exc) -> {
            if (exc != null) {
                toDeferredResult().fail(exc);
            } else {
                toDeferredResult().complete(body);
            }
        });
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy