package com.atlassian.bitbucket.mesh.config;

import com.atlassian.bitbucket.mesh.annotation.ManagedByControlPlane;
import com.atlassian.bitbucket.mesh.repository.Repository;
import com.atlassian.bitbucket.mesh.repository.RepositoryHashService;
import com.atlassian.bitbucket.mesh.transaction.QuorumMode;

import javax.annotation.Nonnull;
import java.time.Duration;
import java.util.Set;

/**
 * Application configuration properties related to replication and transactions.
 */
public interface ReplicationConfig {

    /**
     * The frequency for forced content hash recalculation.
     * <p>
     * The content hash for a repository is updated when processing a {@code git} {@code reference-transaction} hook
     * callback. The new content hash is usually calculated via an incremental hashing approach, which involves
     * calculating a {@link RepositoryHashService#calculateTransactionHash(Set) hash representing the ref updates} and
     * then {@link RepositoryHashService#compareAndUpdateContentHash(Repository, String, String, boolean)
     * incrementally updating} the existing content hash.
     * <p>
     * Incremental hashing avoids having to process every ref in the repository on every write (a full recalculation of
     * the content hash). However, if the content hash becomes incorrect then incremental hashing will never be able to
     * fix it. To assist with self-healing the hash calculation process during writes can be configured to force a full
     * content hash recalculation (at a desired frequency). This process is more expensive but ensures the resultant
     * content hash is correct.
     *
     * @return the frequency at which full content hash recalculation is used instead of incremental hashing
     * @see RepositoryHashService
     * @since 2.0.9, 2.1.3, 2.2
     */
    @ManagedByControlPlane
    double getContentHashForcedRecalculationFrequency();

    /**
     * After the followers vote on a transaction and the leader sends the commit or roll back instruction, this
     * defines the interval the leader waits for followers to finalize the transaction. If any followers don't
     * finalize within this interval, the leader will assume they failed to finalize, mark them inconsistent and
     * move forward with its processing.
     *
     * @return the interval the transaction leader should wait for followers to finalize a transaction
     */
    @Nonnull
    Duration getFinalizeInterval();

    /**
     * @return controls how replica votes are applied, when replicating a transaction
     */
    @ManagedByControlPlane
    @Nonnull
    QuorumMode getQuorumMode();

    /**
     * {@link com.atlassian.bitbucket.mesh.coordination.WriteLock Write locks} are used in replication to serialize
     * write operations in a repository. The write lock implements Maekawa's algorithm, which includes a mechanism
     * to request a previously granted token to be yielded back so it can be granted to a higher priority transaction.
     * <p>
     * This setting controls how soon another token yield request should be sent to the current holder if the holder
     * does not yield the token.
     *
     * @return the interval at which yield requests should be retried if they're not honored by the token holder
     */
    @Nonnull
    Duration getYieldTokenRetryInterval();
}
