@Subscribe
  @Transactional
  public void onServiceComponentHostEvent(ServiceComponentUninstalledEvent event) {

    m_lock.lock();

    try {
      Cluster cluster = clusters.get().getClusterById(event.getClusterId());
      List<HostVersionEntity> hostVersionEntities =
          hostVersionDAO.get().findByClusterAndHost(cluster.getClusterName(), event.getHostName());

      for (HostVersionEntity hostVersionEntity : hostVersionEntities) {
        HostEntity hostEntity = hostVersionEntity.getHostEntity();
        RepositoryVersionEntity repoVersionEntity = hostVersionEntity.getRepositoryVersion();
        StackId stackId = repoVersionEntity.getStackId();

        if (null == stackId) {
          LOG.info("Stack id could not be loaded for host version {}, repo {}", hostVersionEntity.getHostName(),
              repoVersionEntity.getVersion());
          continue;
        }

        RepositoryVersionState repoState = checkAllHostComponents(stackId, hostEntity);
        if (null != repoState) {
          hostVersionEntity.setState(repoState);
          hostVersionDAO.get().merge(hostVersionEntity);
        }
      }

    } catch (AmbariException e) {
      LOG.error("Cannot update states after a component was uninstalled: {}", event, e);
    } finally {
      m_lock.unlock();
    }
  }
The publisher may be an asynchronous, multi-threaded one, so to avoid the (rare, but possible) case
of both an Install and Uninstall event occurring at the same time, we use a Lock.
ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/HostVersionOutOfSyncListener.java