package com.atlassian.bitbucket.mesh.management;

import com.atlassian.bitbucket.mesh.rpc.v1.RpcSidebandFollowerFragment;

import javax.annotation.Nonnull;

/**
 * Manages sideband connections to the control plane. Sideband connections are bidirectional streaming requests
 * initiated by the control plane which allow Mesh to {@link #send} requests of its own.
 */
public interface SidebandManager {

    /**
     * Opens a new sideband connection and returns a {@link SidebandReceiver receiver} that can handle messages
     * that are sent from the control plane to Mesh. The provided {@link SidebandSender sender} is used to
     * {@link #send} messages from Mesh to the control plane.
     *
     * @param parameters parameters describing the sideband connection
     * @return a receiver to handle incoming messages from the control plane
     */
    @Nonnull
    SidebandReceiver open(@Nonnull OpenSidebandParameters parameters);

    /**
     * Attempts to send the provided message to the control plane via an open sideband connection. If there are
     * no open sideband connections, the message may be queued. Messages are <i>not</i> queued if there are any
     * open sideband connections, even if it cannot be sent to any of them.
     * <p>
     * <b>Note</b>: Just because {@code true} is returned does not mean the message will be delivered. Even if
     * there was an open sideband connection to send it with, {@code true} only means there was no <i>immediate
     * failure</i> trying to call {@link SidebandSender#send send}. On the other hand, a {@code false} return
     * <i>does</i> mean the message will not be delivered.
     *
     * @param fragment the message to send
     * @return {@code true} if a sideband connection accepted the message, or if the message was added to the
     *         queue; otherwise, {@code false} if the queue was full or the message could not be sent
     */
    boolean send(@Nonnull RpcSidebandFollowerFragment fragment);
}
