package com.atlassian.bitbucket.mesh.request;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * Provides <i>immutable</i> access to metadata about a request, which can be useful for logging and other purposes.
 * Some metadata properties are likely to change as a request is processed:
 * <ul>
 *     <li>{@link #getBytesReceived()}</li>
 *     <li>{@link #getBytesSent()}</li>
 *     <li>{@link #getMessagesReceived()}</li>
 *     <li>{@link #getMessagesSent()}</li>
 *     <li>{@link #getResult()}</li>
 * </ul>
 * During request processing, these properties may return <i>interim or incomplete</i> values.
 */
public interface RequestMetadata {

    /**
     * @return the action requested, such as a gRPC service name
     */
    @Nonnull
    String getAction();

    /**
     * @return the agent that made the request
     */
    @Nullable
    String getAgent();

    /**
     * @return the number of bytes received <i>so far</i>; this value may increase as the request is processed
     */
    long getBytesReceived();

    /**
     * @return the number of bytes sent <i>so far</i>; this value may increase as the request is processed
     */
    long getBytesSent();

    /**
     * @return a correlation ID which can be used to associate processing from this request with additional logging
     *         on the remote client
     */
    @Nullable
    String getCorrelationId();

    /**
     * @return the number of messages received <i>so far</i> while processing this request; this value may increase
     *         as the request is processed
     */
    int getMessagesReceived();

    /**
     * @return the number of messages sent <i>so far</i> while processing this request; this value may increase as
     *         the request is processed
     */
    int getMessagesSent();

    /**
     * @return the request's protocol
     */
    @Nonnull
    String getProtocol();

    /**
     * @return the address of the remote client where the request originated
     */
    @Nullable
    String getRemoteAddress();

    /**
     * @return a code indicating the result of processing the request, if the request is complete; otherwise,
     *         {@code null} if the result is not yet known
     */
    @Nullable
    Integer getResult();

    /**
     * @return the remote user associated with the request, if any
     */
    @Nullable
    String getUser();
}
