Queue::runLoop() - Add explanatory exit message for an aborted queue
authorTim Otten <totten@civicrm.org>
Tue, 3 Oct 2023 01:45:27 +0000 (18:45 -0700)
committerTim Otten <totten@civicrm.org>
Tue, 3 Oct 2023 01:45:27 +0000 (18:45 -0700)
Civi/Api4/Action/Queue/RunLoop.php
tests/phpunit/api/v4/Entity/QueueTest.php

index 5a777b3ab2636404dd6867f31d8a604bf5d8f856..498064c39bfa30471032fc9890b4e331959549e8 100644 (file)
@@ -67,6 +67,7 @@ class RunLoop extends \Civi\Api4\Generic\AbstractAction {
 
     while (TRUE) {
       if (!$queue->isActive()) {
+        $message = sprintf('Queue is not active (status => %s)', $queue->getStatus());
         break;
       }
 
index e15eb9e364f99baf995d9fb7cbe119844f10626f..5da25ca24d461a80b1e2fbcca277636adf23522e 100644 (file)
@@ -214,6 +214,43 @@ class QueueTest extends Api4TestBase {
     $this->assertEquals(0, $result[0]['queue_total'], 'Queue should be empty');
   }
 
+  public function testRunLoop_abort() {
+    $queueName = 'QueueTest_' . md5(random_bytes(32)) . '_runloopabort';
+    $queue = \Civi::queue($queueName, [
+      'type' => 'Sql',
+      'runner' => 'task',
+      'error' => 'abort',
+    ]);
+    $this->assertQueueStats(0, 0, 0, $queue);
+
+    \Civi::queue($queueName)->createItem(new \CRM_Queue_Task([__CLASS__, 'dummyTask'], ['ok'])); /*A*/
+    \Civi::queue($queueName)->createItem(new \CRM_Queue_Task([__CLASS__, 'dummyTask'], ['ok'])); /*B*/
+    \Civi::queue($queueName)->createItem(new \CRM_Queue_Task([__CLASS__, 'dummyTask'], ['ok'])); /*C*/
+    \Civi::queue($queueName)->createItem(new \CRM_Queue_Task([__CLASS__, 'dummyTask'], ['exception'])); /*D*/
+    \Civi::queue($queueName)->createItem(new \CRM_Queue_Task([__CLASS__, 'dummyTask'], ['ok']));  /*E*/
+
+    // 20 items ==> 4 per batch ==> 5 batches. Let's run the first 3...
+    $result = Queue::runLoop(0)->setQueue($queueName)->execute();
+    $this->assertEquals(3, $result[0]['item_successes'], "Executed A+B+C");
+    $this->assertEquals(1, $result[0]['item_errors'], "Exception on D");
+    $this->assertEquals(4, $result[0]['loop_requests'], "Attempted A+B+C+D");
+    $this->assertTrue(is_numeric($result[0]['loop_duration']));
+    $this->assertEquals('Queue is not active (status => aborted)', $result[0]['exit_message']);
+    $this->assertEquals(0, $result[0]['queue_blocked'], 'No tasks are time-blocked (future-scheduled)');
+    $this->assertEquals(2, $result[0]['queue_ready'], 'Need to try D+E');
+    $this->assertEquals(2, $result[0]['queue_total'], 'Need to try D+E');
+  }
+
+  public static function dummyTask(\CRM_Queue_TaskContext $ctx, string $outcome): bool {
+    if ($outcome === 'exception') {
+      throw new \Exception("dummyTask simulated an exception!");
+    }
+    if ($outcome === 'ok') {
+      return TRUE;
+    }
+    static::fail('dummyTask has unrecognized outcome: ' . $outcome);
+  }
+
   /**
    * @param \Civi\Core\Event\GenericHookEvent $e
    * @see CRM_Utils_Hook::queueRun()