onQueue('automations'); } public function handle(AdvanceAutomationRun $advance): void { $this->run->refresh(); if (! in_array($this->run->status, [RunStatus::Pending, RunStatus::Running, RunStatus::Waiting], true)) { return; } if (! $this->run->is_manual && $this->run->automation->status !== AutomationStatus::Active) { return; } $node = collect($this->run->automation->nodes ?? [])->firstWhere('id', $this->nodeId); if ($node === null) { $this->run->update([ 'status' => RunStatus::Failed, 'error' => ['message' => __('automations.errors.node_no_longer_exists', ['node_id' => $this->nodeId])], 'finished_at' => now(), ]); return; } $nodeType = NodeType::from($node['type']); $this->run->update([ 'status' => RunStatus::Running, 'current_node_id' => $this->nodeId, 'started_at' => $this->run->started_at ?? now(), ]); $nodeRun = AutomationNodeRun::create([ 'run_id' => $this->run->id, 'node_id' => $this->nodeId, 'node_type' => $nodeType, 'status' => NodeRunStatus::Running, 'input' => $this->run->context, 'started_at' => now(), ]); try { $result = $this->executeNode($nodeType, $node['data'] ?? []); } catch (Throwable $e) { $result = NodeRunResult::failed($e->getMessage(), ['class' => $e::class]); } $nodeRun->update([ 'status' => $result->status, 'output' => $result->output, 'error' => $result->error, 'finished_at' => now(), ]); if ($result->status === NodeRunStatus::Failed) { $this->run->update([ 'status' => RunStatus::Failed, 'error' => array_merge(['node_id' => $this->nodeId], $result->error ?? []), 'finished_at' => now(), ]); return; } $this->run->update([ 'context' => array_merge($this->run->context ?? [], $result->output), ]); if ($result->sleepUntil !== null) { $this->run->update([ 'status' => RunStatus::Waiting, 'next_action_at' => $result->sleepUntil, ]); return; } $advance($this->run, $this->nodeId, $result->nextHandle); } public function failed(?Throwable $e): void { $this->run->refresh(); if (in_array($this->run->status, [RunStatus::Completed, RunStatus::Failed], true)) { return; } $this->run->update([ 'status' => RunStatus::Failed, 'error' => ['message' => $e?->getMessage() ?? 'job failed', 'node_id' => $this->nodeId], 'finished_at' => now(), ]); } private function executeNode(NodeType $type, array $config): NodeRunResult { $handler = match ($type) { NodeType::Generate => app(RunGenerateNode::class), NodeType::Delay => app(RunDelayNode::class), NodeType::Condition => app(RunConditionNode::class), NodeType::Publish => app(RunPublishNode::class), NodeType::Webhook => app(RunWebhookNode::class), NodeType::End => app(RunEndNode::class), NodeType::FetchRss => app(RunFetchRssNode::class), NodeType::HttpRequest => app(RunHttpRequestNode::class), NodeType::Trigger => throw new LogicException('Trigger nodes are not executed as run steps.'), }; return $handler($this->run, $config); } }