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

# Corrutinas y trabajos asincrónicos.

> Naturaleza suspendida del cliente y manejo de 202 (auto-asíncrono) con SDK de Kotlin.

# Corrutinas y trabajos asincrónicos

Todos los métodos `MarkpdfClient` son `suspend fun`: no bloquean el hilo mientras esperan la respuesta HTTP y se integran naturalmente con `viewModelScope`, `lifecycleScope`, `Dispatchers.IO` o cualquier `CoroutineScope` propio.

Además, hay un mecanismo separado en el servidor: cuando todos los servidores de conversión están saturados, API responde a `202` con un `job_id` en lugar de bloquear la solicitud. Consulte [`GET /jobs/{id}`](/docs/public/es/api/jobs).

## Uso básico con `runBlocking`

Para scripts o `main()`:

```kotlin theme={null}
fun main() = runBlocking {
    val client = MarkpdfClient(apiKey = "YOUR_API_KEY")
    val result = client.convertFile(File("report.pdf"))
    // ...
}
```

## De `ViewModel` (Android)

```kotlin theme={null}
class ConvertViewModel(private val client: MarkpdfClient) : ViewModel() {

    private val _markdown = MutableStateFlow<String?>(null)
    val markdown: StateFlow<String?> = _markdown

    fun convert(file: File) {
        viewModelScope.launch {
            val result = client.convertFile(file, ConvertOptions(mode = ConversionMode.FAST))
            if (result is ConvertResult.Markdown) {
                _markdown.value = result.markdown
            }
        }
    }
}
```

## Conversiones paralelas con `async`

```kotlin theme={null}
suspend fun convertAll(files: List<File>): List<ConvertResult> = coroutineScope {
    files.map { file ->
        async { client.convertFile(file) }
    }.awaitAll()
}
```

<Warning>
  La paralelización agresiva de solicitudes puede desencadenar `429`. Limite la simultaneidad (por ejemplo, con `Semaphore(n)` alrededor de cada `async`) si convierte muchos documentos a la vez.
</Warning>

## Empleos por saturación (202)

De forma predeterminada, todos los métodos de conversión manejan `202` de forma transparente (`ConvertOptions.autoPoll` es `true`):

```kotlin theme={null}
// SDK waits and polls automatically, without blocking the thread
val result = client.convertFile(File("report.pdf"))
```

### Manual de encuestas

```kotlin theme={null}
val result = client.convertFile(
    File("report.pdf"),
    ConvertOptions(autoPoll = false),
)

when (result) {
    is ConvertResult.Queued -> {
        println("En cola: ${result.job.jobId}")
        val finalJob = client.waitForJob(result.job.jobId, pollInterval = 5.seconds)

        if (finalJob.status == JobStatus.COMPLETED) {
            val markdown = finalJob.body?.jsonPrimitive?.content
        } else {
            error(finalJob.error ?: "job falló")
        }
    }
    is ConvertResult.Markdown -> println(result.markdown)
    is ConvertResult.Json -> {}
}
```

### Exponer el progreso como `Flow`

```kotlin theme={null}
fun watchJob(client: MarkpdfClient, jobId: String): Flow<Job> = flow {
    var job = client.getJob(jobId)
    emit(job)
    while (job.status == JobStatus.QUEUED || job.status == JobStatus.PROCESSING) {
        delay(5.seconds)
        job = client.getJob(jobId)
        emit(job)
    }
}
```

<Tip>
  En condiciones de carga normales, no verá `202`; solo sucede cuando todos los backends están saturados. `autoPoll: true` (el valor predeterminado) ya lo cubre sin código adicional en la mayoría de los casos.
</Tip>

<Warning>
  Los resultados de los trabajos completados caducan en aproximadamente 1 hora. Si guarda un `jobId` y recibe `404` al consultarlo, reenvíe la conversión original.
</Warning>
