private void handleUpdateErrorOnMasterThread(WmTezSession session,
      int failedEndpointVersion, IdentityHashMap<WmTezSession, GetRequest> toReuse,
      WmThreadSyncWork syncWork, HashSet<String> poolsToRedistribute) {
    // First, check if the registry has been updated since the error, and skip the error if
    // we have received new, valid registry info (TODO: externally, add a grace period for this?).
    Ref<Integer> endpointVersion = new Ref<>(-1);
    AmPluginInfo info = session.getAmPluginInfo(endpointVersion);
    if (info != null && endpointVersion.value > failedEndpointVersion) {
      LOG.info("Ignoring an update error; endpoint information has been updated to {}", info);
      return;
    }
    GetRequest reuseRequest = toReuse.remove(session);
    if (reuseRequest != null) {
      // This session is bad, so don't allow reuse; just convert it to normal get.
      reuseRequest.sessionToReuse = null;
    }

    // We are assuming the update-error AM is bad and just try to kill it.
    RemoveSessionResult rr = checkAndRemoveSessionFromItsPool(
        session, poolsToRedistribute, null, true);
    switch (rr) {
    case OK:
    case NOT_FOUND:
      // Regardless whether it was removed successfully or after failing to remove, restart it.
      // Since we just restart this from under the user, mark it so we handle it properly when
      // the user tries to actually use this session and fails, proceeding to return/destroy it.
      session.setIsIrrelevantForWm("Failed to update resource allocation");
      // We assume AM might be bad so we will not try to kill the query here; just scrap the AM.
      // TODO: propagate this error to TezJobMonitor somehow? Without using killQuery
      syncWork.toRestartInUse.add(session);
      break;
    case IGNORE:
      return; // An update error for some session that was actually already killed by us.
    default:
      throw new AssertionError("Unknown state " + rr);
    }
  }
This is the main method of the master thread the processes one set of events.
Be mindful of the fact that events can be queued while we are processing events, so
in addition to making sure we keep the current set consistent (e.g. no need to handle
update errors for a session that should already be destroyed), this needs to guard itself
against the future iterations - e.g. what happens if we kill a query due to plan change,
but the DAG finished before the kill happens and the user queues a "return" event? Etc.
DO NOT block for a long time in this method.
@param e Input events.
@param syncWork Output tasks that cannot be called via async methods.
ql/src/java/org/apache/hadoop/hive/ql/exec/tez/WorkloadManager.java