class ShardService {

    public void recoverSharding() {
        ShardRecovery recovery = shardRecoveryDao.getLatestShardRecovery();
        boolean isShardingOff = propertiesHolder.getBooleanProperty("apl.noshardcreate", false);
        boolean shardingEnabled = blockchainConfig.getCurrentConfig().isShardingEnabled();
        boolean shardingEnabledRecoveryExists = shardingEnabled && recovery != null;
        boolean doRecovery = !isShardingOff && shardingEnabledRecoveryExists && recovery.getState() != MigrateState.COMPLETED;
        boolean deleteRecovery = isShardingOff && shardingEnabledRecoveryExists && recovery.getState() == MigrateState.INIT;
        log.debug("do recovery = '{}' parts : (!{} && {} && {} && {})",
            doRecovery,
            isShardingOff,
            shardingEnabled,
            recovery != null,
            recovery != null ? recovery.getState() != MigrateState.COMPLETED : "false"
        );
        if (doRecovery) {
            isSharding = true;
            long start = System.currentTimeMillis();
            try {
                // here we are able to recover from stored record
                aplAppStatus.durableTaskStart("sharding", "Blockchain db sharding process takes some time, pls be patient...", true);
                Shard lastShard = shardDao.getLastShard();
                shardMigrationExecutor.prepare();
                shardMigrationExecutor.createAllCommands(lastShard.getShardHeight(), lastShard.getShardId(), recovery.getState());
                shardMigrationExecutor.executeAllOperations();
                log.info("Finished sharding by recovery, height='{}' in {} ms", recovery.getHeight(), System.currentTimeMillis() - start);
                aplAppStatus.durableTaskFinished("sharding", false, "Shard process finished");
            } finally {
                isSharding = false;
            }
            // when sharding was disabled but recovery records was stored before
            // let's remove records for sharding recovery + shard
        } else if (deleteRecovery) {
            deleteRecovery(recovery);
        }
    }

    @Inject public  ShardService(ShardDao shardDao, BlockchainProcessor blockchainProcessor, Blockchain blockchain,
                        DirProvider dirProvider, Zip zip, DatabaseManager databaseManager,
                        BlockchainConfig blockchainConfig, ShardRecoveryDao shardRecoveryDao,
                        ShardMigrationExecutor shardMigrationExecutor, AplAppStatus aplAppStatus,
                        PropertiesHolder propertiesHolder, Event<TrimConfig> trimEvent, GlobalSync globalSync,
                        TrimService trimService, Event<DbHotSwapConfig> dbEvent);

}