Repository: pimcore/pimcore (language: php)

Issue:
[Improvement]: Various improvements for generic execution engine
### Improvement description

- `gee_job_cancelled` doesnt get translated
- Add generic start information (JobName, JobId, Action, TimeStamp) to the log before executing the job
- Add generic end information (same as above) to the log after execution the job
- Improve "No subject found" error message with more details


Discussion / hints:

Fix patch:
diff --git a/bundles/GenericExecutionEngineBundle/src/Agent/JobExecutionAgent.php b/bundles/GenericExecutionEngineBundle/src/Agent/JobExecutionAgent.php
index 303a9d09141..18a3b482388 100644
--- a/bundles/GenericExecutionEngineBundle/src/Agent/JobExecutionAgent.php
+++ b/bundles/GenericExecutionEngineBundle/src/Agent/JobExecutionAgent.php
@@ -17,6 +17,7 @@
 namespace Pimcore\Bundle\GenericExecutionEngineBundle\Agent;
 
 use Doctrine\DBAL\Exception;
+use Pimcore\Bundle\GenericExecutionEngineBundle\Extractor\JobRunExtractorInterface;
 use Pimcore\Bundle\GenericExecutionEngineBundle\Entity\JobRun;
 use Pimcore\Bundle\GenericExecutionEngineBundle\Exception\InvalidErrorHandlingModeException;
 use Pimcore\Bundle\GenericExecutionEngineBundle\Messenger\Messages\GenericExecutionEngineMessageInterface;
@@ -39,6 +40,7 @@ final class JobExecutionAgent implements JobExecutionAgentInterface
     use StopMessengerWorkersTrait;
 
     private const LOG_JOB_RUN_ID_KEY = '%job_run_id%';
+    private const LOG_JOB_RUN_NAME_KEY = '%job_run_name%';
 
     private bool $isDev;
 
@@ -68,6 +70,11 @@ public function startJobExecution(
         $jobRun->setCurrentStep(0);
         $jobRun->setTotalElements(count($job->getSelectedElements()));
 
+        $this->jobRunRepository->updateLogLocalizedWithDomain(
+            $jobRun,
+            'gee_job_started',
+            $this->getLogParams($jobRun)
+        );
         $this->jobRunRepository->update($jobRun);
 
         $this->dispatchStepMessage($jobRun);
@@ -113,10 +120,10 @@ public function cancelJobRun(int $jobRunId): void
         $jobRun = $this->jobRunRepository->getJobRunById($jobRunId, true);
         $this->genericExecutionEngineLogger->info("[JobRun {$jobRun->getId()}]: JobRun cancelled.");
         $jobRun->setState(JobRunStates::CANCELLED);
-        $this->jobRunRepository->updateLogLocalized(
+        $this->jobRunRepository->updateLogLocalizedWithDomain(
             $jobRun,
             'gee_job_cancelled',
-            $this->getLogParams($jobRun->getId())
+            $this->getLogParams($jobRun)
         );
     }
 
@@ -158,7 +165,7 @@ private function continueJobStepExecution(GenericExecutionEngineMessageInterface
             $this->setJobRunError(
                 $jobRun,
                 'gee_error_no_job_definition',
-                $this->getLogParams($jobRun->getId())
+                $this->getLogParams($jobRun)
             );
 
             return;
@@ -259,10 +266,10 @@ private function stopJobExecutionOnError(
         $this->stopMessengerWorkers();
         $this->setJobRunError($jobRun, $errorMessage, [], false);
         $this->genericExecutionEngineLogger->info("[JobRun {$jobRun->getId()}]: JobRun cancelled due to errors.");
-        $this->jobRunRepository->updateLogLocalized(
+        $this->jobRunRepository->updateLogLocalizedWithDomain(
             $jobRun,
             'gee_job_failed',
-            $this->getLogParams($jobRun->getId())
+            $this->getLogParams($jobRun)
         );
     }
 
@@ -290,7 +297,11 @@ private function setJobRunError(
             $this->genericExecutionEngineLogger->info(
                 "[JobRun {$jobRun->getId()}]: " . $translatedMessage . ' --> Job execution failed.'
             );
-            $this->jobRunRepository->updateLogLocalized($jobRun, $errorMessage, $params);
+            $this->jobRunRepository->updateLogLocalizedWithDomain(
+                $jobRun,
+                $errorMessage,
+                $params
+            );
         } else {
             $this->genericExecutionEngineLogger->info(
                 "[JobRun {$jobRun->getId()}]: " . $errorMessage . ' --> Job execution failed.'
@@ -329,7 +340,7 @@ private function dispatchStepMessage(JobRun $jobRun): void
             $this->setJobRunError(
                 $jobRun,
                 'gee_error_missing_message_implementation',
-                ['%message%' => $messageString, '%job_name%' => $job->getName()]
+                ['%message%' => $messageString, '%job_run_name%' => $job->getName()]
             );
 
             return;
@@ -352,30 +363,44 @@ private function dispatchStepMessage(JobRun $jobRun): void
         }
     }
 
-    private function getLogParams(int $jobRunId): array
+    private function getLogParams(JobRun $jobRun): array
     {
-        return [self::LOG_JOB_RUN_ID_KEY => $jobRunId];
+        return [
+            self::LOG_JOB_RUN_ID_KEY => $jobRun->getId(),
+            self::LOG_JOB_RUN_NAME_KEY => $jobRun->getJob()?->getName()
+        ];
     }
 
+    /**
+     * @throws Exception
+     */
     private function setCompletionState(JobRun $jobRun): void
     {
+        $message = '';
 
         $logs = $this->jobRunErrorLogRepository->getLogsByJobRunId(
             $jobRun->getId(),
             $jobRun->getCurrentStep()
         );
 
+        if(count($logs) === $jobRun->getTotalElements()) {
+            $jobRun->setState(JobRunStates::FAILED);
+            $message = 'gee_job_failed';
+        } else if(count($logs) > 0) {
+            $jobRun->setState(JobRunStates::FINISHED_WITH_ERRORS);
+            $message = 'gee_job_finished_with_errors';
+        }
+
         if(empty($logs)) {
             $jobRun->setCurrentMessage(null);
             $jobRun->setState(JobRunStates::FINISHED);
-
-            return;
+            $message = 'gee_job_finished';
         }
 
-        if(count($logs) === $jobRun->getTotalElements()) {
-            $jobRun->setState(JobRunStates::FAILED);
-        } else {
-            $jobRun->setState(JobRunStates::FINISHED_WITH_ERRORS);
-        }
+        $this->jobRunRepository->updateLogLocalizedWithDomain(
+            $jobRun,
+            $message,
+            $this->getLogParams($jobRun)
+        );
     }
 }
diff --git a/bundles/GenericExecutionEngineBundle/src/Messenger/Handler/AbstractAutomationActionHandler.php b/bundles/GenericExecutionEngineBundle/src/Messenger/Handler/AbstractAutomationActionHandler.php
index a246746d39f..201b4ec07c3 100644
--- a/bundles/GenericExecutionEngineBundle/src/Messenger/Handler/AbstractAutomationActionHandler.php
+++ b/bundles/GenericExecutionEngineBundle/src/Messenger/Handler/AbstractAutomationActionHandler.php
@@ -197,7 +197,14 @@ protected function getSubjectFromMessage(
         );
 
         if (!$subject) {
-            throw new UnexpectedValueException('No subject type found');
+            throw new UnexpectedValueException(
+                sprintf(
+                    'No subject type found. Expected types: %s, found %s, %s',
+                    implode(', ', $types),
+                    $message->getElement()?->getId(),
+                    $message->getElement()?->getType()
+                )
+            );
         }
 
         return $subject;
diff --git a/bundles/GenericExecutionEngineBundle/src/Repository/JobRunRepository.php b/bundles/GenericExecutionEngineBundle/src/Repository/JobRunRepository.php
index 4630fc3dba0..2136c1bddba 100644
--- a/bundles/GenericExecutionEngineBundle/src/Repository/JobRunRepository.php
+++ b/bundles/GenericExecutionEngineBundle/src/Repository/JobRunRepository.php
@@ -67,16 +67,16 @@ public function update(JobRun $jobRun): JobRun
 
     /**
      * @throws Exception
+     * @internal
      */
-    public function updateLogLocalized(
+    public function updateLogLocalizedWithDomain(
         JobRun $jobRun,
         string $message,
         array $params = [],
         bool $updateCurrentMessage = true,
-        string $defaultLocale = 'en'
+        string $defaultLocale = 'en',
+        string $domain = 'admin'
     ): void {
-        $domain = $this->executionContext->getTranslationDomain($jobRun->getExecutionContext());
-
         if ($updateCurrentMessage) {
             $jobRun->setCurrentMessageLocalized(
                 $this->currentMessageProvider->getTranslationMessages($message, $params, $domain)
@@ -88,6 +88,24 @@ public function updateLogLocalized(
         $this->updateLog($jobRun, $translatedMessage);
     }
 
+    public function updateLogLocalized(
+        JobRun $jobRun,
+        string $message,
+        array $params = [],
+        bool $updateCurrentMessage = true,
+        string $defaultLocale = 'en'
+    ): void {
+        $domain = $this->executionContext->getTranslationDomain($jobRun->getExecutionContext());
+
+        $this->updateLogLocalizedWithDomain(
+            $jobRun,
+            $message,
+            $params,
+            $updateCurrentMessage,
+            $defaultLocale,
+            $domain);
+    }
+
     /**
      * @throws Exception
      */
diff --git a/bundles/GenericExecutionEngineBundle/src/Repository/JobRunRepositoryInterface.php b/bundles/GenericExecutionEngineBundle/src/Repository/JobRunRepositoryInterface.php
index 2ddc8c5141e..1da12e8d1da 100644
--- a/bundles/GenericExecutionEngineBundle/src/Repository/JobRunRepositoryInterface.php
+++ b/bundles/GenericExecutionEngineBundle/src/Repository/JobRunRepositoryInterface.php
@@ -26,15 +26,25 @@ public function createFromJob(Job $job, int $ownerId = null): JobRun;
 
     public function update(JobRun $jobRun): JobRun;
 
+    public function updateLogLocalized(
+        JobRun $jobRun,
+        string $message,
+        array $params = [],
+        bool $updateCurrentMessage = true,
+        string $defaultLocale = 'en'
+    ): void;
+
     /**
      * @throws Exception
+     * @internal
      */
-    public function updateLogLocalized(
+    public function updateLogLocalizedWithDomain(
         JobRun $jobRun,
         string $message,
         array $params = [],
         bool $updateCurrentMessage = true,
-        string $defaultLocale = 'en'
+        string $defaultLocale = 'en',
+        string $domain = 'admin'
     ): void;
 
     /**
diff --git a/bundles/GenericExecutionEngineBundle/translations/admin.en.yaml b/bundles/GenericExecutionEngineBundle/translations/admin.en.yaml
index 34ac38df937..b2d1a25ea33 100644
--- a/bundles/GenericExecutionEngineBundle/translations/admin.en.yaml
+++ b/bundles/GenericExecutionEngineBundle/translations/admin.en.yaml
@@ -1,8 +1,11 @@
 gee_job_run_permission: Job Run Overview
 gee_see_all_job_runs_permission: See all Job Runs
 gee_error_no_job_definition: No Job definition found for Job Run ID %job_run_id%.
-gee_error_missing_message_implementation: Step message implementation %message% of Job %job_name% not found.
-gee_error_no_steps: Job definition %job_name% has no steps defined.
-gee_job_cancelled: Job Run ID %job_run_id% execution cancelled.
-gee_job_failed: Job Run ID %job_run_id% execution failed.
-gee_middleware_step_condition_not_met: Skipping step %stepName% with id %stepId% in %jobName%, condition not met.
\ No newline at end of file
+gee_error_missing_message_implementation: Step message implementation %message% of Job %job_run_name% not found.
+gee_error_no_steps: Job definition %job_run_name% has no steps defined.
+gee_job_cancelled: Job Run %job_run_name% (%job_run_id%) cancelled
+gee_job_failed: Job Run %job_run_name% (%job_run_id%) failed.
+gee_middleware_step_condition_not_met: Skipping step %stepName% with id %stepId% in %jobName%, condition not met.
+gee_job_started: Job Run %job_run_name% (%job_run_id%) started.
+gee_job_finished: Job Run %job_run_name% (%job_run_id%) completed successfully.
+gee_job_finished_with_errors: Job Run %job_run_name% (%job_run_id%) completed with errors.
\ No newline at end of file


Test patch: