---
name: job_worker
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func JobWorker(ctx context.Context, q *JobQueue, handler JobHandler, opts ...WorkerOption) error"
description: "Ejecuta un poll loop bloqueante que desencola y procesa jobs hasta que el context sea cancelado. El handler determina complete vs fail. Opciones: WithPollInterval (default 1s), WithJobTypes."
tags: [job, queue, worker, goroutine, poll, async, background, infra, concurrency]
uses_functions: [job_dequeue_go_infra, job_complete_go_infra, job_fail_go_infra]
uses_types: [job_queue_go_infra, job_go_infra]
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [context, fmt, time]
params:
  - name: ctx
    desc: "context que al cancelarse detiene el worker limpiamente (graceful shutdown)"
  - name: q
    desc: "cola de jobs creada con JobQueueCreate"
  - name: handler
    desc: "funcion que procesa un job; retorno nil = completado, error = fallo"
  - name: opts
    desc: "opciones: WithPollInterval(d), WithJobTypes(types...)"
output: "ctx.Err() cuando el context se cancela, o error de configuracion"
tested: true
tests:
  - "worker_graceful_shutdown"
  - "worker_processes_jobs"
test_file_path: "functions/infra/job_queue_test.go"
file_path: "functions/infra/job_worker.go"
---

## Ejemplo

```go
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

go JobWorker(ctx, q, func(job Job) error {
    fmt.Println("processing", job.ID, job.Type)
    return nil // complete
}, WithPollInterval(500*time.Millisecond), WithJobTypes("send_email"))
```

## Notas

Funcion bloqueante — ejecutar en una goroutine. Retorna `ctx.Err()` cuando el context se cancela (graceful shutdown). Los errores transitorios de dequeue (DB) generan un sleep y retry. El handler tiene la responsabilidad completa del procesamiento; JobWorker se encarga de complete/fail.
