ソースを参照

feat: record which runner produced an execution

runnerId was already in the executions view's field list and in the API
response, but nothing ever wrote it, so it was null on every row and a Runner
column would have been permanently empty.

The workflow engine had no idea which runner it belonged to. Its config now
carries the runner id, the runner service passes its own in, and every
execution records it. The executions list shows it alongside the trigger, so a
run can be attributed to a runner without reading logs.

Verified: an execution produced after the change reports runner-1, while
earlier ones remain null.
fszontagh 1 ヶ月 前
親
コミット
905ad798f8

+ 1 - 0
src/runner/runner_service.cpp

@@ -321,6 +321,7 @@ RunnerService::RunnerService(const RunnerServiceConfig& config)
 
     // Initialize workflow engine
     config_.workflow_engine_config.max_concurrent_executions = config_.max_concurrent_executions;
+    config_.workflow_engine_config.runner_id = config_.runner_id;
     engine_ = std::make_unique<WorkflowEngine>(*registry_, *storage_, config_.workflow_engine_config);
 
     // Set up credential auth callback for workflow engine

+ 2 - 0
src/runner/workflow_engine.cpp

@@ -111,6 +111,7 @@ nlohmann::json ExecutionResult::toJson() const {
     // Note: id is managed by database as _id (execution_id is passed to storage_.insert)
     j["workflowId"] = workflow_id;
     j["workflowName"] = workflow_name;
+    j["runnerId"] = runner_id;
     j["status"] = executionStatusToString(status);
     j["triggerType"] = trigger_type;
     j["triggerData"] = truncateLargeValues(trigger_data);
@@ -199,6 +200,7 @@ Result<ExecutionResult> WorkflowEngine::execute(const Workflow& workflow,
     // Create execution record
     ExecutionResult result;
     result.execution_id = UUID::generatePrefixed("exec");
+    result.runner_id = config_.runner_id;
     result.workflow_id = workflow.id;
     result.workflow_name = workflow.name;
     result.status = ExecutionStatus::Running;

+ 4 - 0
src/runner/workflow_engine.hpp

@@ -88,6 +88,7 @@ struct ExecutionResult {
     std::string execution_id;
     std::string workflow_id;
     std::string workflow_name;
+    std::string runner_id;
     ExecutionStatus status = ExecutionStatus::Pending;
     std::string trigger_type;
     nlohmann::json trigger_data;
@@ -107,6 +108,9 @@ using ExecutionCallback = std::function<void(const std::string& event,
 
 // Workflow engine configuration
 struct WorkflowEngineConfig {
+    // Recorded on every execution this engine runs, so a stored execution says
+    // which runner produced it.
+    std::string runner_id;
     int64_t default_timeout_ms = 60000;
     int max_concurrent_executions = 10;
     size_t script_engine_pool_size = 4;

+ 2 - 0
webui/src/api/workflows.ts

@@ -288,6 +288,7 @@ export interface ExecutionListItem {
   workflowName: string
   status: string
   triggerType: string
+  runnerId: string
   error: string
   startedAt: number
   finishedAt: number
@@ -301,6 +302,7 @@ function transformExecutionListItem(data: any): ExecutionListItem {
     workflowName: data.workflowName,
     status: data.status,
     triggerType: data.triggerType || '',
+    runnerId: data.runnerId || '',
     error: data.error || '',
     startedAt: data.startedAt,
     finishedAt: data.finishedAt,

+ 6 - 0
webui/src/pages/ExecutionsPage.tsx

@@ -114,6 +114,9 @@ export default function ExecutionsPage() {
                   <th className="px-4 py-3 text-left text-sm font-medium text-gray-600 dark:text-gray-300">
                     Trigger
                   </th>
+                  <th className="px-4 py-3 text-left text-sm font-medium text-gray-600 dark:text-gray-300">
+                    Runner
+                  </th>
                   <th className="px-4 py-3 text-left text-sm font-medium text-gray-600 dark:text-gray-300">
                     Started
                   </th>
@@ -160,6 +163,9 @@ export default function ExecutionsPage() {
                     <td className="px-4 py-3 align-top text-gray-600 dark:text-gray-400">
                       {execution.triggerType}
                     </td>
+                    <td className="px-4 py-3 align-top text-gray-600 dark:text-gray-400 text-sm">
+                      {execution.runnerId || '-'}
+                    </td>
                     <td className="px-4 py-3 align-top text-gray-500 dark:text-gray-400 text-sm">
                       {execution.startedAt
                         ? safeFormatDistanceToNow(execution.startedAt)