{
  "license": "CC BY 4.0",
  "licenseUrl": "https://creativecommons.org/licenses/by/4.0/",
  "recipe": {
    "slug": "missed-cron-schedules",
    "title": "Detect Missed Cron Schedules",
    "testedWith": "Apache DataFusion 45.2.0",
    "lastReviewed": "2026-07-28"
  },
  "contract": {
    "tableName": "cron_runs",
    "schema": [
      {
        "name": "timestamp_utc",
        "type": "Timestamp",
        "description": "Observed cron-run start time."
      },
      {
        "name": "schedule_name",
        "type": "Utf8",
        "description": "Stable scheduled-workflow name."
      },
      {
        "name": "environment",
        "type": "Utf8",
        "description": "Deployment environment."
      },
      {
        "name": "expected_interval_minutes",
        "type": "Float64",
        "description": "Documented minutes between starts."
      }
    ]
  },
  "query": "WITH ordered_runs AS (\n  SELECT\n    schedule_name,\n    environment,\n    timestamp_utc AS run_at,\n    expected_interval_minutes,\n    LAG(timestamp_utc) OVER (\n      PARTITION BY schedule_name, environment\n      ORDER BY timestamp_utc\n    ) AS previous_run_at\n  FROM cron_runs\n  WHERE timestamp_utc >= now() - INTERVAL '7 days'\n)\nSELECT\n  schedule_name,\n  environment,\n  previous_run_at,\n  run_at,\n  expected_interval_minutes,\n  date_part('second', run_at - previous_run_at) / 60.0 AS observed_gap_minutes\nFROM ordered_runs\nWHERE previous_run_at IS NOT NULL\n  AND date_part('second', run_at - previous_run_at) / 60.0\n    > expected_interval_minutes * 1.5\nORDER BY observed_gap_minutes DESC;",
  "fixtureKind": "schema-example",
  "inputRows": [
    {
      "timestamp_utc": "2026-07-28T10:00:00Z",
      "schedule_name": "schedule_name_example_1",
      "environment": "production",
      "expected_interval_minutes": 12
    },
    {
      "timestamp_utc": "2026-07-28T11:00:00Z",
      "schedule_name": "schedule_name_example_2",
      "environment": "production",
      "expected_interval_minutes": 37
    },
    {
      "timestamp_utc": "2026-07-28T12:00:00Z",
      "schedule_name": "schedule_name_example_3",
      "environment": "production",
      "expected_interval_minutes": 24
    }
  ],
  "illustrativeInputRows": [
    {
      "timestamp_utc": "2026-07-28T10:00:00Z",
      "schedule_name": "schedule_name_example_1",
      "environment": "production",
      "expected_interval_minutes": 12
    },
    {
      "timestamp_utc": "2026-07-28T11:00:00Z",
      "schedule_name": "schedule_name_example_2",
      "environment": "production",
      "expected_interval_minutes": 37
    },
    {
      "timestamp_utc": "2026-07-28T12:00:00Z",
      "schedule_name": "schedule_name_example_3",
      "environment": "production",
      "expected_interval_minutes": 24
    }
  ],
  "expectedOutput": {
    "columns": [
      "schedule_name",
      "environment",
      "previous_run_at",
      "run_at",
      "expected_interval_minutes",
      "observed_gap_minutes"
    ],
    "rows": [
      {
        "schedule_name": "hourly_billing_sync",
        "environment": "production",
        "previous_run_at": "2026-07-27 07:00",
        "run_at": "2026-07-27 10:00",
        "expected_interval_minutes": 60,
        "observed_gap_minutes": 180
      },
      {
        "schedule_name": "daily_trial_expiration",
        "environment": "production",
        "previous_run_at": "2026-07-25 02:00",
        "run_at": "2026-07-27 02:00",
        "expected_interval_minutes": 1440,
        "observed_gap_minutes": 2880
      }
    ]
  },
  "notes": [
    "The compact input rows demonstrate field names and JSON types; they are not claimed to generate the displayed aggregate by themselves.",
    "The expected output is deterministic synthetic review data for the documented output shape.",
    "Adapt time windows, thresholds, identities, and business definitions before operational use."
  ]
}