# Job Lifecycle Long-running work must run through jobs. ## Job statuses ```text queued running succeeded failed cancelled ``` ## Job table fields - id - job_type - status - project_id - dataset_id nullable - analysis_run_id nullable - progress_percent nullable - message nullable - error_code nullable - error_detail nullable - created_at - started_at - finished_at ## Job types - dataset_metadata_extract - raster_clip - raster_tile - vector_import - vector_clip - grb_fetch - object_detection - segmentation - qaqc_compare - export_generate ## Job events Each status transition should create a domain event. ## API behavior Starting a long-running operation returns immediately with: ```json { "data": { "job_id": "...", "status": "queued" }, "error": null, "meta": {} } ``` The frontend polls a job endpoint until success or failure. ## Failure handling Jobs must fail loudly and clearly. Do not silently skip processing.