package com.atlassian.bitbucket.mesh.execution;

import io.grpc.stub.StreamObserver;

import javax.annotation.Nonnull;
import java.util.concurrent.Future;

/**
 * Executes gRPC operations off of the main gRPC request threads.
 * <p>
 * This executor
 * <ul>
 *     <li>catches any exceptions thrown by the submitted task and propagates the error to the RPC client,
 *     unless the client has already cancelled the request.</li>
 *     <li>propagates the {@link ExecutionContext} if one is active</li>
 *     <li>propagates the MDC state</li>
 * </ul>
 */
public interface GrpcAsyncExecutor {

    /**
     * @param streamObserver the {@link StreamObserver} associated with the gRPC request
     * @param task the task to execute asynchronously
     * @param <T> the response type
     */
    <T> void execute(@Nonnull StreamObserver<T> streamObserver, @Nonnull Runnable task);

    /**
     * @param streamObserver the {@link StreamObserver} associated with the gRPC request
     * @param task the task to execute asynchronously
     * @param <T> the response type
     */
    @Nonnull
    <T> Future<Void> submit(@Nonnull StreamObserver<T> streamObserver, @Nonnull Runnable task);

    /**
     * Shuts down the executor
     */
    void shutdown();
}
