class UpgradeService {

    public void upgradeUser(String userId) {

        LOG.info("Upgrade process starting for user {}", userId);

        int numberOfTasksApplied = 0;
        for (UpgradeTask task : tasks) {

            // skip non user upgrade task
            if (task.getTarget() != USER) {
                LOG.debug("{} does not target users", task.getId());
                continue;
            }

            final String targetId = USER.name() + '-' + userId;

            if (repository.isAlreadyApplied(targetId, task.getId())) {
                LOG.debug("{} already applied for user {}, let's skip it", task.getId(), userId);
            } else {
                LOG.debug("apply upgrade {} for user {}", task.getId(), userId);
                task.run();
                repository.applied(targetId, task.getId());
                numberOfTasksApplied++;
            }

        }
        LOG.info("Upgrade process finished for user {}, {}/{} upgrade(s) performed", userId, numberOfTasksApplied,
                tasks.size());
    }

}