package com.atlassian.stash.internal.scm.git.upgrade;

/**
 * Describes a synchronous upgrade task which is run while the system is being initialized. Synchronous upgrade tasks
 * are run as part of the application lifecycle as described by {@code LifecycleAware}. That means they run:
 * <ul>
 *     <li><i>After</i> the Spring {@code ApplicationContext} for the plugin has completely initialized</li>
 *     <li><i>Before</i> the web application has fully started</li>
 * </ul>
 * Because the web application has not fully started before these upgrade tasks are run, they do not need to handle
 * concurrency. However, for the same reason, upgrades defined this way must be <i>fast</i>. There is currently no
 * <i>visible</i> feedback loop for such tasks, so slow-running tasks run the risk of being killed by administrators
 * thinking the server is "hung". To try and mitigate that risk, at a minimum upgrade tasks should write to the log
 * regularly to track their progress.
 * <p>
 * When interacting with repositories, there are two primary ways to create a slow upgrade task:
 * <ul>
 *     <li>Forking {@code git}. This may mean:
 *     <ul>
 *         <li>Running very expensive commands, like large {@code git rev-list} walks</li>
 *         <li>Running a large number of inexpensive commands. Even {@code git config} and {@code git update-ref}
 *         become expensive when forked several times</li>
 *     </ul>
 *     </li>
 *     <li>Performing extensive disk I/O, even from Java
 *     <ul>
 *         <li>Ref files, for example, are tiny (only 41 bytes, generally), but reading or writing thousands of
 *         them is likely to be very slow even on fast hardware</li>
 *     </ul>
 *     </li>
 * </ul>
 * When developing synchronous upgrade tasks, remember: The profiling logs are your friend. Also remember that most
 * customer installations do not host their repositories on an SSD!
 *
 * @since 2.9
 */
public interface SynchronousUpgradeTask extends UpgradeTaskSupport {

    /**
     * {@inheritDoc}
     * <p>
     * Synchronous upgrade tasks are applied using SAL's {@code PluginUpgradeTask} mechanism. In addition to the
     * considerations documented on {@link UpgradeTaskSupport#getOrder() UpgradeTaskSupport}, the value returned
     * here is also tied to the {@code build} parameter in {@code atlassian-plugin.xml}. When a new upgrade task
     * is added, the {@code build} parameter must be increased as well or the new task will not run.
     *
     * @return the order in which this upgrade task should be run
     */
    @Override
    int getOrder();
}
