Cliente: Centrica Soluciones
Proyecto: Nebula ERP - Componente DataVault
Version: 1.0
Fecha: 16 de marzo, 2026
Autor: Carlos Torres (Arquitecto de Software)
Estado: VIGENTE
El pipeline de ingesta es el proceso central de DataVault. Transforma documentos crudos en paquetes archivisticos OAIS, garantizando preservacion, integridad y trazabilidad.
ENTRADA PROCESAMIENTO SALIDA
| | |
v v v
[Carpeta] --> [Watcher] --> [IngestService] --> [SIP] + [AIP] + [DIP]
ingest_sip/ (Daemon) (.process()) Repositorio/{Proyecto}/
El usuario (via web o SFTP) deposita una carpeta en el directorio de ingesta:
/home/egs/datavault/Repositorio/ingest_sip/
PROYECTO_NOMBRE_CARPETA/
archivo1.pdf
archivo2.xlsx
subdirectorio/
archivo3.docx
Reglas de nomenclatura:
DIGITALIZACION, una carpeta DIGITALIZACION_lote_01 se asigna a ese proyectoDEFAULTEl daemon watcher_datavault.py escanea el directorio cada N segundos (configurable, default: 5s).
Criterio de estabilidad:
# Pseudocodigo del chequeo de estabilidad
tamano_anterior = calcular_tamano(carpeta)
archivos_anterior = contar_archivos(carpeta)
esperar(5_segundos)
tamano_actual = calcular_tamano(carpeta)
archivos_actual = contar_archivos(carpeta)
if tamano_anterior == tamano_actual and archivos_anterior == archivos_actual:
# Carpeta estable -> procesar
else:
# Carpeta en transferencia -> esperar siguiente ciclo
Hallazgo critico: El watcher limpia subdirectorios prohibidos (AIP, DIP, SIP, metadata) dentro de ingest_sip/ como medida de proteccion. Esto evita que paquetes procesados contaminen la carpeta de ingesta.
# Logica real en watcher_datavault.py
def detectar_proyecto(nombre_carpeta):
for proyecto in proyectos_activos:
if nombre_carpeta.startswith(proyecto.name):
return proyecto
return proyecto_default
Observacion: La deteccion por prefijo es fragil. Un proyecto TEST matchearia TESTING_lote_01 incorrectamente. Se recomienda usar delimitadores explicitos (e.g., PROYECTO__nombre_carpeta).
Formato: {nombre_normalizado}_{timestamp}_{hash_corto}
Ejemplo: lote_documentos_20260315_143022_a7b2c1d4
Normalizacion:
_YYYYMMDD_HHMMSSSe verifican tres fuentes antes de proceder:
{PROJECT}/SIP/{unique_id}/?{PROJECT}/AIP/{unique_id}.zip?ingest con mismo local_path?Si hay duplicado, el SIP se mueve a _errores/ con log explicativo.
{PROJECT}/SIP/{unique_id}/
data/
(copia de todos los archivos originales)
metadata/
descriptive_metadata.json
technical_metadata.json
preservation_metadata.json
manifest.xml
{
"dc:title": "lote_documentos",
"dc:creator": "usuario_web",
"dc:date": "2026-03-15T14:30:22",
"dc:format": "application/pdf, application/vnd.openxmlformats",
"dc:identifier": "lote_documentos_20260315_143022_a7b2c1d4",
"dc:source": "DIGITALIZACION",
"dc:description": "Paquete de ingesta automatica"
}
{
"files": [
{
"filename": "archivo1.pdf",
"size_bytes": 1048576,
"md5": "d41d8cd98f00b204e9800998ecf8427e",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"mime_type": "application/pdf"
}
],
"total_files": 3,
"total_size_bytes": 3145728,
"created_at": "2026-03-15T14:30:22"
}
{
"retention_policy": {
"retention_days": 3650,
"legal_hold": false,
"classification": "standard"
},
"integrity": {
"algorithm": "SHA-256",
"package_checksum": "a1b2c3...",
"verified_at": "2026-03-15T14:30:30"
},
"provenance": {
"ingest_method": "automatic_watcher",
"source_system": "DataVault OAIS Server",
"operator": "usuario_web"
}
}
{PROJECT}/AIP/{unique_id}.zipManejo de errores: Si la compresion falla, el SIP permanece intacto. El AIP se marca como fallido pero el proceso continua para intentar generar el DIP.
{PROJECT}/DIP/{unique_id}.zipingest_sip/ a _procesados/ingest con estado completedoais_status.json con estadisticasRepositorio/
ingest_sip/ # WATCH_DIR - entrada de nuevos SIPs
_procesados/ # Archivo de carpetas procesadas exitosamente
_errores/ # Archivo de carpetas fallidas
DEFAULT/ # Proyecto por defecto
SIP/
{id}/
data/
metadata/
manifest.xml
AIP/
{id}.zip
DIP/
{id}.zip
DIGITALIZACION/ # Proyecto especifico
Documentos/
SIP/
AIP/
DIP/
TRASFERENCIA_2022/ # Otro proyecto
SIP/
AIP/
DIP/
| Riesgo | Descripcion | Recomendacion |
|---|---|---|
| Sin transaccionalidad | Si el proceso falla entre paso 6 y 9, puede quedar un SIP parcial sin registro en BD | Implementar patron saga o at-least-once con tabla de estado |
| Polling vs Push | El watcher usa polling cada 5s. Con 1000+ archivos en ingest_sip/ el escaneo se vuelve costoso | Migrar a watchdog (inotify en Linux) |
| Nombre como identificador | La deteccion de proyecto por prefijo de nombre es fragil | Implementar metadata de proyecto en archivo .project.json dentro de la carpeta |
| Sin cola de trabajo | Los SIPs se procesan secuencialmente. Un archivo de 10GB bloquea toda la cola | Implementar cola de trabajo (Celery/RQ) con workers paralelos |
| Sin limites de tamaño | No hay validacion de MAX_UPLOAD_SIZE_MB en el watcher (solo en el API) | Agregar validacion en watcher antes de procesar |
| Operacion | Tiempo estimado (100MB) | Tiempo estimado (1GB) |
|---|---|---|
| Copia de archivos | ~2s | ~15s |
| Calculo SHA-256 | ~1s | ~8s |
| Compresion ZIP (AIP) | ~3s | ~25s |
| Copia ZIP (DIP) | ~2s | ~15s |
| Total pipeline | ~10s | ~70s |
Estos tiempos son estimados para disco SSD. En HDD mecanico, multiplicar por 3-5x.
Departamento de Arquitectura — Centrica Soluciones