public function setExecutionStatusForTask($execution_status, Dunagan_ProcessQueue_Model_Task_Interface $taskObject, $status_message = null)
 {
     $task_id = $taskObject->getId();
     if (empty($task_id)) {
         // TODO Some logging here
         return 0;
     }
     if ($taskObject->isStatusValid($execution_status)) {
         $update_bind_array = array('status' => $execution_status);
         if (!is_null($status_message)) {
             $update_bind_array['status_message'] = $status_message;
         }
         $task_id = $taskObject->getId();
         $where_conditions_array = array('task_id=?' => $task_id);
         $rows_updated = $this->_getWriteAdapter()->update($this->getMainTable(), $update_bind_array, $where_conditions_array);
         return $rows_updated;
     }
     // TODO Log error in this case
     return 0;
 }
 /**
  * Executes the following:
  *  - Attempts to update task object's row as processing
  *  - If successful, Begins a database transaction
  *  - Attempts to select that row for update
  *  - If successful, attempts to execute method callback defined in row, returning a result object
  *  - Updates the task object based on the resulting object
  *  - Commits the database transaction
  *
  * @param Dunagan_ProcessQueue_Model_Task_Interface $processQueueTaskObject
  * @param boolean $row_has_already_been_set_as_processing - Has this task object already been set as processing?
  *                                                              This typically denotes that whatever process created
  *                                                              the task object wants to ensure that it is also the
  *                                                              process which executes the task
  * @return Dunagan_ProcessQueue_Model_Task_Result_Interface|null - Returns an object implementing interface
  *                                                                  Dunagan_ProcessQueue_Model_Task_Result_Interface
  *                                                                  if execution did not throw an uncaught exception
  *                                                                Returns null if the task was unable to be selected
  *                                                                  for processing (another thread has likely already
  *                                                                  begun processing the task) or if an uncaught
  *                                                                  exception was thrown
  */
 public function processQueueTask(Dunagan_ProcessQueue_Model_Task_Interface $processQueueTaskObject, $row_has_already_been_set_as_processing = false)
 {
     if (!$row_has_already_been_set_as_processing) {
         try {
             $able_to_lock_for_processing = $processQueueTaskObject->attemptUpdatingRowAsProcessing();
             if (!$able_to_lock_for_processing) {
                 // Assume another thread of execution is already processing this task
                 return null;
             }
         } catch (Exception $e) {
             $error_message = $this->__(self::EXCEPTION_UPDATE_AS_PROCESSING, $processQueueTaskObject->getId(), $e->getMessage());
             $this->_logError($error_message);
             return null;
         }
     } else {
         // Don't attempt to update the status as PROCESSING, but set the task last executed at time, as well as
         //      clear out the existing status message
         $task_id = $processQueueTaskObject->getId();
         try {
             $this->_getTaskResourceSingleton()->updateLastExecutedAtToCurrentTime(array($task_id), true);
         } catch (Exception $e) {
             $error_message = $this->__(self::EXCEPTION_UPDATING_LAST_EXECUTED_FOR_PRIOR_PROCESSING_TASK, $task_id, $e->getMessage());
             $this->_logError($error_message);
             // Do not interrupt processing of the task due to an exception thrown here
         }
     }
     // At this point, start transaction and lock row for update to ensure exclusive access
     $taskResourceSingleton = $processQueueTaskObject->getResource();
     $taskResourceSingleton->beginTransaction();
     try {
         $selected = $processQueueTaskObject->selectForUpdate();
         if (!$selected) {
             // Assume another thread has already locked this task object's row, although this shouldn't happen
             $taskResourceSingleton->rollBack();
             $error_message = $this->__(self::ERROR_FAILED_TO_SELECT_FOR_UPDATE, $processQueueTaskObject->getId());
             $this->_logError($error_message);
             return null;
         }
     } catch (Exception $e) {
         $taskResourceSingleton->rollBack();
         $error_message = $this->__(self::EXCEPTION_SELECT_FOR_UPDATE, $processQueueTaskObject->getId(), $e->getMessage());
         $this->_logError($error_message);
         return null;
     }
     try {
         $taskExecutionResult = $processQueueTaskObject->executeTask();
     } catch (Dunagan_ProcessQueue_Model_Exception_Rollback $taskExecutionResult) {
         // Rollback the transaction to prevent any orphaned/corrupt data from persisting in the system
         $taskResourceSingleton->rollBack();
         // We still want the task to update its status and status message fields according to the task execution,
         //      so we continue the execution of this method
     } catch (Exception $e) {
         // If the task execution threw an uncaught exception, rollback the transaction and return error status
         $taskResourceSingleton->rollBack();
         $error_message = $this->__(self::EXCEPTION_EXECUTING_TASK, $processQueueTaskObject->getId(), $e->getMessage());
         $processQueueTaskObject->setTaskAsErrored($error_message);
         $this->_logError($error_message);
         return null;
     }
     try {
         $processQueueTaskObject->actOnTaskResult($taskExecutionResult);
     } catch (Exception $e) {
         // At this point, we would assume that the task has been performed successfully since executeTask() did not
         //  throw any exceptions. As such, log the exception but commit the transaction. Even if this leaves a row
         //  in the PROCESSING state, it's better than leaving parts of the database out of sync with external resources
         $error_message = $this->__(self::EXCEPTION_ACTING_ON_TASK_RESULT, $processQueueTaskObject->getId(), $e->getMessage());
         $this->_logError($error_message);
     }
     try {
         // Check to ensure that a rollback transaction exception was not thrown
         if (!$taskExecutionResult->shouldTransactionBeRolledBack()) {
             $taskResourceSingleton->commit();
         }
     } catch (Exception $e) {
         // If an exception occurs here, rollback
         $taskResourceSingleton->rollback();
         $processQueueTaskObject->setTaskAsErrored();
         $error_message = $this->__(self::EXCEPTION_COMMITTING_TRANSACTION, $processQueueTaskObject->getId(), $e->getMessage());
         $this->_logError($error_message);
     }
     return $taskExecutionResult;
 }