> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tetryx.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Jobs and Batches

> How Lynx models simulation work: batches contain jobs

Lynx uses two related concepts for simulation work: **batches** and **jobs**.

## Batch

A batch is the top-level unit of submitted work, created by a single `POST /jobs` call. It represents one Monte Carlo study.

A batch has:

* a unique UUID (`batch_id`)
* a name you provide
* a total job count
* counters for completed and failed jobs
* an overall status: `Pending`, `Running`, `Completed`, `Failed`, or `Cancelled`
* a created timestamp

A batch is complete when all its jobs reach a terminal state.

## Job

A job is one individual simulation run within a batch, created automatically by Lynx when you submit a batch. Each job gets its own sampled parameter set drawn from the dispersions you defined.

A job has:

* a unique UUID (`job_id`)
* a reference to its parent `batch_id`
* the sampled parameters for this run (`run_config`)
* a `status`
* retry tracking: `retries`, `max_retries`
* a timeout: `timeout_secs`
* timestamps: `created_at`, `claimed_at`, `started_at`, `completed_at`
* the ID of the runner that claimed it: `assigned_runner`
* an error message if it failed: `error_message`

## Batch vs job

|                  | Batch                             | Job                            |
| ---------------- | --------------------------------- | ------------------------------ |
| Created by       | Your `POST /jobs` call            | Lynx automatically             |
| Granularity      | One study                         | One parameter sample           |
| Status endpoint  | `GET /batches/{batch_id}`         | `GET /jobs/{job_id}`           |
| Results endpoint | `GET /batches/{batch_id}/results` | `GET /jobs/{job_id}/results`   |
| Retries          | Batches do not retry              | Jobs retry up to `max_retries` |

## Submitting a batch

```bash theme={null}
curl -sS \
  -X POST https://api.lynx.tetryx.io/jobs \
  -H 'content-type: application/json' \
  -d '{
    "name": "spacecraft-analysis-v1",
    "config": {
      "simulation": {
        "name": "Spacecraft Mission Analysis",
        "version": "1.0.0",
        "duration_minutes": 120
      },
      "monte_carlo": {
        "runs": 500,
        "sampling_method": "latin_hypercube",
        "seed": 42
      },
      "dispersions": {
        "mass_kg": {
          "distribution": { "type": "normal", "mean": 2500.0, "std_dev": 125.0 },
          "units": "kg"
        },
        "drag_coefficient": {
          "distribution": { "type": "uniform", "min": 0.28, "max": 0.34 },
          "units": ""
        }
      },
      "compute": {
        "container": {
          "image": "your-org/simulation:latest",
          "cpu_request": "2000m",
          "memory_request": "4Gi"
        },
        "max_parallel_jobs": 20,
        "job_timeout_seconds": 3600
      },
      "early_termination": {
        "enabled": true,
        "check_frequency_hz": 10.0,
        "conditions": [
          {
            "variable": "battery_state_of_charge",
            "condition": "< 0.1",
            "description": "Battery critically low"
          }
        ]
      },
      "telemetry": {
        "sampling_rate_hz": 10.0,
        "variables": ["altitude", "velocity", "battery_state_of_charge"],
        "storage": {
          "s3_bucket": "your-telemetry-bucket",
          "s3_prefix": "spacecraft/",
          "compression": "gzip"
        },
        "buffer_flush_interval_seconds": 30
      }
    }
  }' | jq
```

Use `runs_override` to cap the run count without changing your config — useful for quick validation:

```json theme={null}
{
  "name": "quick-test",
  "runs_override": 3,
  "config": { ... }
}
```

## Monitoring a batch

```bash theme={null}
# Batch status with per-status job counts
curl -s https://api.lynx.tetryx.io/batches/<batch-id> | jq

# All terminal results for the batch
curl -s https://api.lynx.tetryx.io/batches/<batch-id>/results | jq
```

The status response includes:

* `jobs_by_status` — job count for each status (`Pending`, `Running`, `Completed`, `Failed`, etc.)
* `throughput_jobs_per_minute` — current processing rate
* `estimated_completion_time_mins` — time remaining estimate, if computable

## Sampling methods

| Method              | Description                                         |
| ------------------- | --------------------------------------------------- |
| `latin_hypercube`   | Stratified sampling — best coverage with fewer runs |
| `monte_carlo`       | Pure random sampling                                |
| `quasi_monte_carlo` | Low-discrepancy sequence sampling                   |

Latin Hypercube Sampling (`latin_hypercube`) is recommended for most studies. It produces better parameter space coverage than random sampling with the same number of runs.
