satelles-odf-adiutor es una biblioteca PHP asincrónica basada en Swoole para convertir documentos ODF mediante Unoserver.
Está pensada para integrarse con flujos de generación de reportes, documentos, tickets y plantillas ODF, permitiendo convertir archivos a PDF u otros formatos de forma eficiente, escalable y distribuida.
Además de la conversión directa contra Unoserver, el proyecto incluye balanceo entre múltiples instancias, monitoreo de salud, cliente XML-RPC, servidor TCP, cliente TCP, cola Redis opcional, workers, almacenamiento de estado y resultados de jobs.
- Características
- Requisitos
- Instalación
- Configuración de Unoserver
- Uso directo con UnoserverLoadBalancer
- Servidor TCP de conversión
- Cliente TCP
- Cola Redis y workers
- API principal
- Modos de conversión
- Ejemplos incluidos
- Estructura interna
- Recomendaciones
- Licencia
- Conversión de documentos mediante Unoserver.
- Comunicación XML-RPC con instancias de Unoserver.
- Procesamiento asincrónico con Swoole.
- Balanceo de carga entre múltiples servidores.
- Monitoreo de salud con recuperación automática.
- Reintentos configurables.
- Métricas básicas por servidor.
- Soporte para modo
streamy modofile. - Cliente y servidor TCP para conversiones remotas.
- Cola Redis opcional para trabajos diferidos.
- Consulta de estado, cancelación y descarga de resultados.
- Tipado mediante objetos de resultado y excepciones propias.
- PHP
>=8.4 - Extensión
swoole - Extensión
fileinfo - Extensión
dom - Extensión
sockets - Extensión
libxml - Unoserver
- LibreOffice
- Composer
Opcionalmente:
- Extensión
redis, para usar la cola Redis. - Redis Server, para jobs persistentes.
composer require xvii/satelles-odf-adiutorEl paquete usa autoload PSR-4 bajo el namespace:
Tabula17\Satelles\Odf\Adiutor\Para usar la librería debes tener una o más instancias de Unoserver ejecutándose.
unoserver --port 2003 &
unoserver --port 2004 &También puedes iniciar más instancias para distribuir mejor la carga:
unoserver --port 2003 &
unoserver --port 2004 &
unoserver --port 2005 &
unoserver --port 2006 &Para entornos donde necesites administrar varias instancias locales de Unoserver como servicios systemd, el proyecto incluye una sección específica de Pool Manager con script de instalación, configuración de puertos y comandos de gestión.
Consulta la documentación detallada en src/Unoserver/PoolManager/README.md para más información.
Este modo permite convertir documentos directamente desde PHP usando el balanceador de Unoserver.
<?php
require __DIR__ . '/vendor/autoload.php';
use Swoole\Coroutine;
use Tabula17\Satelles\Odf\Adiutor\Unoserver\ServerHealthMonitor;
use Tabula17\Satelles\Odf\Adiutor\Unoserver\UnoserverLoadBalancer;
use Tabula17\Satelles\Utilis\Collection\ConnectionCollection;
use Tabula17\Satelles\Utilis\Config\ConnectionConfig;
Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
$servers = new ConnectionCollection(
new ConnectionConfig([
'name' => 'unoserver-2003',
'host' => '127.0.0.1',
'port' => 2003,
]),
new ConnectionConfig([
'name' => 'unoserver-2004',
'host' => '127.0.0.1',
'port' => 2004,
])
);
$healthMonitor = new ServerHealthMonitor(
servers: $servers,
checkInterval: 30,
failureThreshold: 3,
retryTimeout: 60
);
$converter = new UnoserverLoadBalancer(
healthMonitor: $healthMonitor,
servers: $servers,
concurrency: 20,
timeout: 15
);
Coroutine\run(function () use ($converter): void {
$converter->start();
$result = $converter->convertAsync(
filePath: __DIR__ . '/documento.odt',
outputFormat: 'pdf',
mode: 'stream'
);
if ($result->isStream() && $result->hasBase64Content()) {
file_put_contents(
__DIR__ . '/salida.pdf',
base64_decode($result->base64Content)
);
}
$converter->stop();
});El proyecto incluye un servidor TCP basado en Swoole mediante la clase:
Tabula17\Satelles\Odf\Adiutor\Server\AdiutorTcpEste servidor permite recibir archivos, convertirlos y devolver resultados a clientes remotos.
Acciones soportadas:
| Acción | Descripción |
|---|---|
convert |
Convierte un archivo de forma directa |
submit |
Envía un trabajo a la cola |
status |
Consulta el estado de un job |
cancel |
Cancela un job |
wait |
Espera un job y devuelve el archivo resultante |
getFile |
Descarga el archivo de un job completado |
Ejemplo disponible en:
examples/server.phpEjecución:
php examples/server.phpPor defecto, el ejemplo levanta un servidor TCP en el puerto 9508.
El cliente TCP está disponible mediante:
Tabula17\Satelles\Odf\Adiutor\Client\AdiutorClientTcpPermite conectarse al servidor AdiutorTcp y ejecutar conversiones remotas.
<?php
require __DIR__ . '/vendor/autoload.php';
use Swoole\Coroutine;
use Tabula17\Satelles\Odf\Adiutor\Client\AdiutorClientTcp;
use Tabula17\Satelles\Utilis\Config\TCPServerConfig;
$config = new TCPServerConfig([
'host' => '127.0.0.1',
'port' => 9508,
]);
$client = new AdiutorClientTcp($config);
Coroutine\run(function () use ($client): void {
$client->convertFile(
filePath: __DIR__ . '/documento.odt',
outputPath: __DIR__ . '/salida.pdf',
format: 'pdf'
);
});Métodos principales del cliente:
convertFile(...)convertFileWithProgress(...)convertFileToMemory(...)convertBase64ToMemory(...)submitJobWithFile(...)submitJob(...)waitForFile(...)waitForFileWithProgress(...)getJobStatus(...)cancelJob(...)getFile(...)getFileWithProgress(...)
Ejemplo disponible en:
examples/client.phpEl proyecto incluye componentes para manejar conversiones como jobs persistentes usando Redis.
Componentes principales:
RedisQueueConfigRedisJobQueueRedisJobStateStoreRedisResultStoreRedisRetrySchedulerRetryPolicyConversionWorkerConversionManager
Ejemplo de configuración:
use Tabula17\Satelles\Odf\Adiutor\Unoserver\Queue\RedisJobQueue;
use Tabula17\Satelles\Odf\Adiutor\Unoserver\Queue\RedisJobStateStore;
use Tabula17\Satelles\Odf\Adiutor\Unoserver\Queue\RedisQueueConfig;
use Tabula17\Satelles\Odf\Adiutor\Unoserver\Queue\RedisResultStore;
use Tabula17\Satelles\Odf\Adiutor\Unoserver\Queue\RedisRetryScheduler;
use Tabula17\Satelles\Odf\Adiutor\Unoserver\Queue\RetryPolicy;
$config = new RedisQueueConfig(
host: '127.0.0.1',
port: 6379,
prefix: 'adiutor'
);
$stateStore = new RedisJobStateStore($config);
$resultStore = new RedisResultStore($config);
$retryPolicy = new RetryPolicy(
baseDelaySeconds: 2,
maxDelaySeconds: 60,
jitterRatio: 0.10
);
$retryScheduler = new RedisRetryScheduler($config, $retryPolicy);
$queue = new RedisJobQueue(
config: $config,
stateStore: $stateStore,
resultStore: $resultStore,
retryScheduler: $retryScheduler
);La cola Redis permite:
- enviar trabajos asincrónicos
- consultar estado
- almacenar resultados
- programar reintentos
- manejar fallos persistentes
- usar dead-letter queue
Monitorea el estado de las instancias de Unoserver.
Responsabilidades:
- verificar disponibilidad
- marcar servidores como saludables o no saludables
- aplicar umbral de fallos
- reintentar servidores después de un timeout
- exponer servidores saludables al balanceador
Coordina la selección de servidores y ejecuta conversiones.
Métodos principales:
start()stop()isRunning()convertSync(...)convertAsync(...)getServerMetrics()getServerPool()getTimeout()setTimeout(...)
Cliente XML-RPC de bajo nivel para comunicarse con Unoserver.
Responsabilidades:
- abrir conexión
- construir request HTTP/XML-RPC
- enviar conversión
- interpretar respuesta
- manejar faults XML-RPC
- devolver
UnoserverConversionResult
Objeto de resultado de conversión.
Propiedades principales:
modeinputPathoutputPathbase64ContentserverHostserverPort
Métodos auxiliares:
isStream()isFile()hasBase64Content()hasOutputPath()
Coordina operaciones de alto nivel sobre la cola y el worker.
Procesa jobs pendientes usando el UnoserverLoadBalancer.
Servidor TCP de conversión de archivos.
Cliente TCP para consumir el servidor de conversión.
La conversión devuelve el contenido codificado en base64 dentro del resultado.
Es útil cuando quieres procesar el archivo en memoria o devolverlo directamente desde una API.
$result = $converter->convertAsync(
filePath: 'documento.odt',
outputFormat: 'pdf',
mode: 'stream'
);
if ($result->isStream() && $result->hasBase64Content()) {
file_put_contents(
'salida.pdf',
base64_decode($result->base64Content)
);
}La conversión genera un archivo en una ruta de salida.
Es útil para reportes grandes o workflows donde el archivo final debe quedar persistido en disco.
$result = $converter->convertAsync(
filePath: 'documento.odt',
outputFormat: 'pdf',
outPath: 'salida.pdf',
mode: 'file'
);
if ($result->isFile() && $result->hasOutputPath()) {
echo "Archivo generado en: {$result->outputPath}\n";
}| Modo | Resultado | Ideal para |
|---|---|---|
stream |
Contenido base64 en memoria | APIs, respuestas HTTP, postprocesado inmediato |
file |
Archivo generado en disco | Documentos grandes, almacenamiento, procesos batch |
El directorio examples incluye scripts de referencia:
examples/example.php
examples/server.php
examples/client.phpphp examples/example.phpphp examples/server.phpphp examples/client.phpAntes de ejecutar los ejemplos asegúrate de tener:
- Unoserver corriendo en los puertos configurados.
- Redis corriendo si vas a usar el ejemplo de servidor con cola.
- Directorios de salida con permisos de escritura.
src/
├── Client/
│ └── AdiutorClientTcp.php
├── Config/
│ └── UnoserverLoadBalancerConfig.php
├── Exceptions/
│ ├── AdiutorException.php
│ ├── InvalidArgumentException.php
│ ├── RuntimeException.php
│ └── Unoserver/
├── Server/
│ ├── AdiutorActionsEnum.php
│ └── AdiutorTcp.php
└── Unoserver/
├── Job/
├── PoolManager/
├── Queue/
├── Service/
├── Worker/
├── ServerHealthMonitor.php
├── ServerHealthMonitorInterface.php
├── UnoserverConversionResult.php
├── UnoserverLoadBalancer.php
├── UnoserverXmlRpcClient.php
└── UnoserverXmlRpcClientInterface.php
- Usa múltiples instancias de Unoserver para mejorar la concurrencia.
- Para gestionar varias instancias locales con
systemd, revisasrc/Unoserver/PoolManager/README.md. - Usa
streampara archivos pequeños o respuestas inmediatas. - Usa
filepara documentos grandes o procesamiento batch. - Configura correctamente permisos de escritura en directorios de salida.
- Usa Redis si necesitas jobs persistentes, reintentos y consulta de estado.
- Mantén monitoreo activo en entornos productivos.
- Ajusta
concurrency,timeoutymaxRetriessegún la carga esperada. - Evita cargar documentos muy grandes en memoria si no es necesario.
Este proyecto usa licencia MIT. Consulta el archivo LICENSE para más detalles.