class WorkerRecoveryManagerImpl implements WorkerRecoveryManager {

	public void doRecovery(){
        try {
            boolean toRestart = Boolean.getBoolean("cloudslang.worker.restart.on.recovery");
            //If we are configured to restart on recovery - do shutdown
            if(toRestart){
                logger.warn("Worker is configured to restart on recovery and since internal recovery is needed the process is exiting...");
                System.exit(EXIT_STATUS);
            }

            synchronized (this){
                //If already in recovery - then return and do nothing
                if(inRecovery){
                    return;
                }
                inRecovery = true;

            }
            syncManager.startRecovery();

            logger.warn("Worker internal recovery started");

            for (WorkerRecoveryListener listener : listeners){
                try {
                    listener.doRecovery();
                } catch (Exception ex) {
                    logger.error("Failed on worker internal recovery", ex);
                }
            }
            if (logger.isDebugEnabled()) logger.debug("Listeners recovery is done");

            retryTemplate.retry(RetryTemplate.INFINITELY, 30*1000L, new RetryTemplate.RetryCallback() {
                @Override
                public void tryOnce() {
					if(logger.isDebugEnabled()) logger.debug("sending worker UP");
                    String newWrv = workerNodeService.up(System.getProperty("worker.uuid"), workerVersionService.getWorkerVersion(), workerVersionService.getWorkerVersionId());
                    setWRV(newWrv);
                    if(logger.isDebugEnabled()) logger.debug("the worker is UP");
                }
            });
            inRecovery = false;
            logger.warn("Worker recovery is done");
        } finally {
            syncManager.finishRecovery();
		}
	}

}