class ReadReplicaStartupProcess implements Lifecycle {

    @Override
    public void start() throws IOException, DatabaseShutdownException
    {
        boolean syncedWithUpstream = false;
        TimeoutStrategy.Timeout timeout = timeoutStrategy.newTimeout();
        int attempt = 0;
        while ( !syncedWithUpstream )
        {
            attempt++;
            MemberId source = null;
            try
            {
                source = selectionStrategy.bestUpstreamDatabase();
                syncStoreWithUpstream( source );
                syncedWithUpstream = true;
            }
            catch ( UpstreamDatabaseSelectionException e )
            {
                lastIssue = issueOf( "finding upstream member", attempt );
                debugLog.warn( lastIssue );
            }
            catch ( StoreCopyFailedException e )
            {
                lastIssue = issueOf( format( "copying store files from %s", source ), attempt );
                debugLog.warn( lastIssue );
            }
            catch ( StoreIdDownloadFailedException e )
            {
                lastIssue = issueOf( format( "getting store id from %s", source ), attempt );
                debugLog.warn( lastIssue );
            }
            catch ( TopologyLookupException e )
            {
                lastIssue = issueOf( format( "getting address of %s", source ), attempt );
                debugLog.warn( lastIssue );
            }

            try
            {
                Thread.sleep( timeout.getMillis() );
                timeout.increment();
            }
            catch ( InterruptedException e )
            {
                Thread.interrupted();
                lastIssue = "Interrupted while trying to start read replica";
                debugLog.warn( lastIssue );
                break;
            }
        }

        if ( !syncedWithUpstream )
        {
            userLog.error( lastIssue );
            throw new RuntimeException( lastIssue );
        }

        try
        {
            localDatabase.start();
            txPulling.start();
        }
        catch ( Throwable e )
        {
            throw new RuntimeException( e );
        }
    }

      ReadReplicaStartupProcess( RemoteStore remoteStore, LocalDatabase localDatabase, Lifecycle txPulling,
            UpstreamDatabaseStrategySelector selectionStrategy, TimeoutStrategy timeoutStrategy, LogProvider debugLogProvider,
            LogProvider userLogProvider, StoreCopyProcess storeCopyProcess, TopologyService topologyService );

}