# Trabajos y trabajos por lotes El trabajo largo corre en segundo plano como un trabajo, que usted sigue por su ID. | Usted quiere | Use | | --- | --- | | Cambiar filas con unas pocas sentencias SQL, publicadas a la vez | `nexus.start_batch_job()` | | Ejecutar su propio script de Spark en Python | `nexus.jobs.submit()` | ## Antes de empezar [#antes-de-empezar] - El **Acceso** de su clave permite escribir. - El espacio de trabajo tiene créditos; si no, un trabajo se rechaza antes de empezar. - Todos los ejemplos suponen `nexus = Nexus.connect()`. Un trabajo gasta los créditos del espacio de trabajo mientras corre. Revise su saldo en . ## Trabajos por lotes [#trabajos-por-lotes] Un trabajo por lotes ejecuta de 1 a 50 sentencias SQL que cambian filas y las publica como un solo cambio: llegan todas, o ninguna. ### Inicie un trabajo por lotes [#inicie-un-trabajo-por-lotes] ```python title="close_old_orders.py" import time from klarety import Nexus, RefusedError, WaitingForOwnerError with Nexus.connect() as nexus: try: job = nexus.start_batch_job([ "UPDATE orders SET status = 'closed' WHERE ordered_at < DATE '2026-01-01'", "DELETE FROM orders WHERE status = 'test'", ]) except RefusedError as refused: raise SystemExit(f"Refused: {refused}") try: state = nexus.jobs.describe(job["job_id"]) while state["state"] in ("running", "publishing"): time.sleep(5) state = nexus.jobs.describe(job["job_id"]) print("Ended as", state["state"]) except WaitingForOwnerError as waiting: print("Waiting for the owner's OK:", waiting, waiting.job_id) ``` ### Sígalo [#sígalo] `jobs.describe()` informa `running`, luego `publishing` y luego cómo terminó el trabajo: `succeeded`, `failed`, `declined` o `expired`. Algunos cambios necesitan el visto bueno del dueño de los datos. Entonces `jobs.describe()` lanza `WaitingForOwnerError` con el `job_id` para seguirlo. El trabajo queda en espera, no falló: nunca lo reenvíe. ### Reglas [#reglas] - Cada sentencia debe leer o cambiar filas. Cambie columnas con [Tablas y esquemas](/docs/es/developers/tables). - Una tabla vacía no tiene desde dónde partir. Agregue sus primeras filas con `tables.edit_rows()` o con una carga. ## Trabajos con script de Spark [#trabajos-con-script-de-spark] `jobs.submit()` ejecuta un script de Spark en Python dentro de los recursos que permite su plan. ### Envíe un script [#envíe-un-script] ```python from klarety import Nexus, RefusedError with Nexus.connect() as nexus: try: job = nexus.jobs.submit(script_uri, args=["--day", "2026-11-09"]) except RefusedError as refused: raise SystemExit(f"Job refused: {refused}") print(job["job_id"], job["state"]) ``` - `script_uri` es un archivo `.py` en el almacenamiento propio de su espacio de trabajo; cualquier otro lugar se rechaza. - `args` se pasan al script, hasta 64. - Un trabajo corre como máximo lo que su plan permite correr a una sentencia. ### Sígalo o cancélelo [#sígalo-o-cancélelo] ```python print(nexus.jobs.describe(job["job_id"])) # submitted, running, succeeded, failed or cancelled nexus.jobs.cancel(job["job_id"]) ``` Cuando un trabajo falla, `exit_reason` dice por qué. ## Qué puede salir mal [#qué-puede-salir-mal] | Excepción | Causa | Qué hacer | | --- | --- | --- | | `RefusedError` | Una sentencia no cambia filas, el script no es un `.py` de su almacenamiento, o pidió más de lo que permite su plan. | Lea el mensaje y corrija la solicitud. | | `InsufficientCreditsError` | El espacio de trabajo no puede pagar el trabajo. | Agregue créditos. | | `WaitingForOwnerError` | El cambio espera el visto bueno del propietario. | Siga `job_id`; no lo reenvíe. | | `NotFoundError` | No existe ese trabajo. | Revise el ID. | ## Próximos pasos [#próximos-pasos] - [Ejecutar SQL](/docs/es/developers/sql) para lecturas. - [Sesiones de Spark](/docs/es/developers/spark) para Spark interactivo. - [Límites y límites de solicitudes](/docs/es/developers/limits) para los recursos de trabajos de su plan.