registry = $registry; } /** * Execute all registered triggers for a LineList save operation * * @param mixed $lineListData The current line list data * @param mixed $beforeData The line list data before changes (null for new records) * @param array $changedFields Array of field names that changed * @param bool $isNewRecord Whether this is a new record * @return array Results from all executed triggers */ public function executeTriggers( $lineListData, $beforeData = null, array $changedFields = [], bool $isNewRecord = false ): array { $this->overallStartTime = microtime(true); Log::info("=== LINE LIST SAVE TRIGGER STARTED ===", [ 'line_list_id' => $lineListData->id, 'line_no' => $lineListData->line_no ?? 'NULL', 'timestamp' => now()->toDateTimeString(), 'is_new_record' => $isNewRecord, 'changed_fields_count' => count($changedFields), 'changed_fields' => $changedFields ]); // Set database timeouts for long-running operations TransactionHelper::setDatabaseTimeouts(300, 600, 600); $results = []; $triggers = $this->registry->getTriggersInOrder(); foreach ($triggers as $index => $trigger) { // Check if trigger should run if (!$trigger->shouldRun($changedFields, $isNewRecord)) { Log::info("Skipping trigger: {$trigger->getName()}", [ 'reason' => 'shouldRun returned false', 'position' => $index + 1 ]); continue; } // Execute trigger synchronously (LineList triggers don't support async) try { $result = $trigger->execute($lineListData, $beforeData, [ 'changed_fields' => $changedFields, 'is_new_record' => $isNewRecord, 'beforeData' => $beforeData, 'lineList' => $lineListData ]); $results[$trigger->getName()] = $result; } catch (\Throwable $th) { Log::error("Trigger execution failed: {$trigger->getName()}", [ 'error' => $th->getMessage(), 'file' => $th->getFile(), 'line' => $th->getLine(), 'trace' => $th->getTraceAsString() ]); // Re-throw for critical triggers (first 5 in registry), log for non-critical ones if ($index < 5) { throw $th; } else { $results[$trigger->getName()] = [ 'error' => $th->getMessage(), 'critical' => false ]; } } } $this->logOverallCompletion($lineListData->id); return $results; } /** * Log overall completion summary */ protected function logOverallCompletion($lineListId) { $overallDuration = round((microtime(true) - $this->overallStartTime) * 1000, 2); Log::info("=== LINE LIST SAVE TRIGGER COMPLETED ===", [ 'line_list_id' => $lineListId, 'timestamp' => now()->toDateTimeString(), 'total_execution_time_ms' => $overallDuration, 'total_execution_time_sec' => round($overallDuration / 1000, 3), 'peak_memory_usage_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2) ]); } }