Pulse Execution History

Related: pulse-async-ix.md - Core Pulse architecture

Overview

Execution history tracking for Pulse scheduled jobs, enabling users to view past job runs with logs, timing data, and status information.

Features

Database Schema

pulse_executions Table

CREATE TABLE IF NOT EXISTS pulse_executions (
    id TEXT PRIMARY KEY,                    -- ASID format: PX_{random}_{timestamp}
    scheduled_job_id TEXT NOT NULL,         -- FK to scheduled_jobs(id)
    async_job_id TEXT,                      -- Optional FK to async_jobs(id)

    -- Execution status
    status TEXT NOT NULL,                   -- 'running', 'completed', 'failed'

    -- Timing
    started_at TEXT NOT NULL,               -- RFC3339 timestamp
    completed_at TEXT,                      -- RFC3339 timestamp (null if running)
    duration_ms INTEGER,                    -- Milliseconds (null if running)

    -- Output capture
    logs TEXT,                              -- Captured stdout/stderr
    result_summary TEXT,                    -- Brief summary
    error_message TEXT,                     -- Error if failed

    -- Metadata
    created_at TEXT NOT NULL,               -- RFC3339 timestamp
    updated_at TEXT NOT NULL,               -- RFC3339 timestamp

    FOREIGN KEY (scheduled_job_id) REFERENCES scheduled_jobs(id)
);

CREATE INDEX idx_pulse_executions_job ON pulse_executions(scheduled_job_id);
CREATE INDEX idx_pulse_executions_status ON pulse_executions(status);
CREATE INDEX idx_pulse_executions_started ON pulse_executions(started_at);

API Endpoints

List Executions

GET /api/pulse/jobs/{job_id}/executions?limit=50&offset=0&status=completed

Response:

{
  "executions": [
    {
      "id": "PX_abc123_1733450123",
      "scheduled_job_id": "SPJ_1733450000",
      "status": "completed",
      "started_at": "2025-12-06T02:00:00Z",
      "completed_at": "2025-12-06T02:00:12Z",
      "duration_ms": 12340,
      "result_summary": "Processed successfully",
      "error_message": null
    }
  ],
  "count": 1,
  "total": 47,
  "has_more": true
}

Type Reference: See Execution and ListExecutionsResponse type definitions.

Get Execution Details

GET /api/pulse/executions/{execution_id}

Response:

{
  "id": "PX_abc123_1733450123",
  "status": "completed",
  "started_at": "2025-12-06T02:00:00Z",
  "completed_at": "2025-12-06T02:00:12Z",
  "duration_ms": 12340,
  "logs": "[2025-12-06T02:00:00Z] Starting job\n[2025-12-06T02:00:12Z] Completed",
  "result_summary": "Processed successfully"
}

Get Execution Logs

GET /api/pulse/executions/{execution_id}/logs

Response: Plain text logs

Implementation

Ticker Integration

Applications using Pulse should integrate execution tracking in their ticker:

// Create execution record before job runs
execution := &models.PulseExecution{
    ID:             id.GenerateExecutionID(),
    ScheduledJobID: job.ID,
    Status:         "running",
    StartedAt:      time.Now().Format(time.RFC3339),
}
db.CreatePulseExecution(execution)

// Execute job
result, err := executeJob(job)

// Update execution with results
execution.CompletedAt = timePtr(time.Now())
execution.DurationMs = intPtr(durationMs)

if err != nil {
    execution.Status = "failed"
    execution.ErrorMessage = stringPtr(err.Error())
} else {
    execution.Status = "completed"
    execution.ResultSummary = stringPtr(result.Summary)
}

db.UpdatePulseExecution(execution)

Storage Layer

Files:

Key Methods:

API Handlers

File: internal/server/pulse_execution_handlers.go

Implements REST endpoints for:

Frontend Integration

TypeScript Types

export type ExecutionStatus = "running" | "completed" | "failed";

export interface PulseExecution {
  id: string;
  scheduled_job_id: string;
  async_job_id?: string;
  status: ExecutionStatus;
  started_at: string;
  completed_at?: string;
  duration_ms?: number;
  result_summary?: string;
  error_message?: string;
}

API Client

export async function listExecutions(
  jobId: string,
  limit = 50,
  offset = 0,
  status?: ExecutionStatus
): Promise<ListExecutionsResponse>

export async function getExecutionLogs(
  executionId: string
): Promise<string>

UI Components

Job Detail Panel - Displays execution history:

Styling:

Real-time Updates

WebSocket Messages

Applications can broadcast execution status changes:

// Execution started
{
  "type": "pulse_execution_started",
  "execution_id": "PX_abc123",
  "job_id": "SPJ_123"
}

// Execution completed
{
  "type": "pulse_execution_completed",
  "execution_id": "PX_abc123",
  "job_id": "SPJ_123",
  "duration_ms": 12340
}

// Execution failed
{
  "type": "pulse_execution_failed",
  "execution_id": "PX_abc123",
  "job_id": "SPJ_123",
  "error": "Operation failed"
}

Testing

Unit Tests

Integration Tests

Future Enhancements

Related Documentation