public void doWork() throws InterruptedException {
    List<HostRoleCommand> tasks = db.getTasksByRoleAndStatus(Role.AMBARI_SERVER_ACTION.name(),
      HostRoleStatus.QUEUED);

    if ((tasks != null) && !tasks.isEmpty()) {
      for (HostRoleCommand task : tasks) {
        Long taskId = task.getTaskId();

        LOG.debug("Processing task #{}", taskId);

        if (task.getStatus() == HostRoleStatus.QUEUED) {
          ExecutionCommandWrapper executionWrapper = task.getExecutionCommandWrapper();

          if (executionWrapper != null) {
            ExecutionCommand executionCommand = executionWrapper.getExecutionCommand();

            if (executionCommand != null) {
              // For now, execute only one task at a time. This may change in the future in the
              // event it is discovered that this is a bottleneck. Since this implementation may
              // change, it should be noted from outside of this class, that there is no expectation
              // that tasks will be processed in order or serially.
              Worker worker = new Worker(task, executionCommand);
              Thread workerThread = new Thread(worker, String.format("Server Action Executor Worker %s", taskId));
              Long timeout = determineTimeout(executionCommand);

              updateHostRoleState(task, executionCommand, createInProgressReport());

              LOG.debug("Starting Server Action Executor Worker thread for task #{}.", taskId);
              workerThread.start();

              try {
                workerThread.join(timeout);
              } catch (InterruptedException e) {
                // Make sure the workerThread is interrupted as well.
                workerThread.interrupt();
                throw e;
              }

              if (workerThread.isAlive()) {
                LOG.debug("Server Action Executor Worker thread for task #{} timed out - it failed to complete within {} ms.",
                    taskId, timeout);
                workerThread.interrupt();
                updateHostRoleState(task, executionCommand, createTimedOutReport());
              } else {
                LOG.debug("Server Action Executor Worker thread for task #{} exited on its own.", taskId);
                updateHostRoleState(task, executionCommand, worker.getCommandReport());
              }
            } else {
              LOG.warn("Task #{} failed to produce an ExecutionCommand, skipping.", taskId);
            }
          } else {
            LOG.warn("Task #{} failed to produce an ExecutionCommandWrapper, skipping.", taskId);
          }
        } else {
          LOG.warn("Queued task #{} is expected to have a status of {} but has a status of {}, skipping.",
              taskId, HostRoleStatus.QUEUED, task.getStatus());
        }
      }
    }
  }
Execute the logic to handle each task in the queue in the order in which it was queued.
<p/>
A single task is executed at one time, allowing for a specified (ExecutionCommand.KeyNames.COMMAND_TIMEOUT)
or the default timeout for it to complete before considering the task timed out.

@throws InterruptedException
ambari-server/src/main/java/org/apache/ambari/server/serveraction/ServerActionExecutor.java