feat: Add database migration service with Alembic for PostgreSQL, integrating job management and counting functionalities. Update Docker Compose to include db-migrations service, enhancing the microservices architecture. Revise documentation for clarity on database schema and migration processes.
This commit is contained in:
+110
-50
@@ -1,6 +1,6 @@
|
||||
// IPSExtractor — esquema de integración PostgreSQL
|
||||
// Fuente: services/extraction/infrastructure/database.py
|
||||
// services/cleaning/infrastructure/database.py
|
||||
// Fuente autoritativa: services/extraction/infrastructure/database.py
|
||||
// services/extraction/alembic/versions/
|
||||
//
|
||||
// Visualizar en https://dbdiagram.io (importar este archivo)
|
||||
// o con la CLI de dbml: npx @dbml/cli dbml2sql docs/database.dbml
|
||||
@@ -8,13 +8,22 @@
|
||||
Project ipsextractor {
|
||||
database_type: 'PostgreSQL'
|
||||
Note: '''
|
||||
Base de datos compartida entre los microservicios de extracción y limpieza.
|
||||
Cada servicio define su propia copia del modelo SQLAlchemy y ejecuta
|
||||
`init_db()` con bloqueo advisory (pg_advisory_lock) para crear tablas
|
||||
sin condiciones de carrera.
|
||||
Base de datos compartida entre todos los microservicios (extraction, cleaning,
|
||||
count-facturas). Cada servicio accede directamente a las tablas que necesita.
|
||||
Las migraciones se gestionan con Alembic (services/extraction/alembic/).
|
||||
Cada servicio es desacoplado; comparten solo la DB como fuente de verdad.
|
||||
'''
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Grupos de tablas
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
TableGroup orchestration {
|
||||
jobs
|
||||
tasks
|
||||
}
|
||||
|
||||
TableGroup pipeline {
|
||||
extraction_batches
|
||||
extraction_rows
|
||||
@@ -22,8 +31,94 @@ TableGroup pipeline {
|
||||
cleaned_rows
|
||||
}
|
||||
|
||||
TableGroup async_jobs {
|
||||
tasks
|
||||
TableGroup counting {
|
||||
count_job_files
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Orchestration — trabajo multimodular del usuario
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Table jobs {
|
||||
id varchar(36) [pk, note: 'UUID v4']
|
||||
status varchar(32) [not null, default: 'pending', note: 'pending | running | completed | failed']
|
||||
title text [note: 'Nombre descriptivo del trabajo']
|
||||
metadata jsonb [not null, default: '{}', note: 'Datos adicionales específicos por tipo de trabajo']
|
||||
created_at timestamptz [not null]
|
||||
updated_at timestamptz [not null]
|
||||
|
||||
indexes {
|
||||
status
|
||||
}
|
||||
|
||||
Note: '''
|
||||
Contenedor de trabajo del usuario. Un job puede tener múltiples tasks
|
||||
(una por servicio/módulo utilizado). Permite agrupar conteo + extracción
|
||||
+ limpieza de un mismo conjunto de documentos.
|
||||
'''
|
||||
}
|
||||
|
||||
Table tasks {
|
||||
id varchar(36) [pk, note: 'UUID v4']
|
||||
job_id varchar(36) [ref: > jobs.id, note: 'FK nullable — compat. con tasks anteriores']
|
||||
type varchar(64) [not null, note: 'counting | extraction | cleaning']
|
||||
status varchar(32) [not null, default: 'pending', note: 'pending | running | completed | failed']
|
||||
title text
|
||||
request jsonb [not null, default: '{}', note: 'Payload de la petición que originó la tarea']
|
||||
result jsonb [not null, default: '{}', note: 'Al completar incluye extraction_batch_id o conteos']
|
||||
error text
|
||||
owner_id varchar(36) [note: 'Reservado para multi-usuario']
|
||||
created_at timestamptz [not null]
|
||||
updated_at timestamptz [not null]
|
||||
started_at timestamptz
|
||||
finished_at timestamptz
|
||||
|
||||
indexes {
|
||||
job_id
|
||||
type
|
||||
status
|
||||
owner_id
|
||||
}
|
||||
|
||||
Note: '''
|
||||
Módulo/resultado dentro de un Job. Una task representa la ejecución
|
||||
de un servicio específico (conteo, extracción, limpieza).
|
||||
job_id es nullable para compatibilidad con tasks creadas antes de jobs.
|
||||
'''
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Counting — resultados del servicio de conteo de facturas médicas
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Table count_job_files {
|
||||
id varchar(36) [pk, note: 'UUID v4']
|
||||
job_module_id varchar(36) [not null, ref: > tasks.id]
|
||||
radicado varchar(255) [note: 'Identificador del radicado / carpeta de origen']
|
||||
filename varchar(512) [not null, note: 'Nombre del archivo PDF']
|
||||
file_path text [note: 'Ruta del archivo en el volumen montado (/data/...)']
|
||||
doc_type varchar(128) [note: 'Tipo de documento (ej. Factura, Historia_Clinica)']
|
||||
service_count integer [note: 'Número de servicios detectados por el modelo ML']
|
||||
services jsonb [not null, default: '[]', note: 'Lista de ServiceRow detectados por el modelo']
|
||||
status varchar(32) [not null, default: 'ok', note: 'ok | error']
|
||||
is_valid boolean [note: 'null=sin revisar | true=válido | false=rechazado por el usuario']
|
||||
error text [note: 'Mensaje de error si status=error']
|
||||
created_at timestamptz [not null]
|
||||
|
||||
indexes {
|
||||
job_module_id
|
||||
radicado
|
||||
status
|
||||
is_valid
|
||||
}
|
||||
|
||||
Note: '''
|
||||
Resultado del servicio Go (services-count-facturas-medicas-serving) para
|
||||
un PDF individual. El campo file_path permite que el servicio de extracción
|
||||
procese el archivo directamente sin necesidad de re-subirlo.
|
||||
is_valid=null hasta que el usuario revise; el umbral min_service_count
|
||||
se aplica en el endpoint POST /tasks/extraction/from-count.
|
||||
'''
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -32,18 +127,20 @@ TableGroup async_jobs {
|
||||
|
||||
Table extraction_batches {
|
||||
id varchar(36) [pk, note: 'UUID v4']
|
||||
job_module_id varchar(36) [ref: > tasks.id, note: 'FK nullable — tarea que origino este lote']
|
||||
status varchar(32) [not null, default: 'pending', note: 'pending | running | completed | failed']
|
||||
root_path text [note: 'Ruta raíz de documentos procesados (IPS_DOCUMENT_ROOT)']
|
||||
request jsonb [not null, default: '{}', note: 'ExtractionRequest serializado (keywords, fields, doc_types, etc.)']
|
||||
root_path text [note: 'Ruta raíz de documentos (IPS_DOCUMENT_ROOT o "count://" si viene de conteo)']
|
||||
request jsonb [not null, default: '{}', note: 'ExtractionRequest serializado']
|
||||
error text
|
||||
created_at timestamptz [not null]
|
||||
updated_at timestamptz [not null]
|
||||
|
||||
indexes {
|
||||
job_module_id
|
||||
status
|
||||
}
|
||||
|
||||
Note: 'Lote creado al iniciar una extracción; agrupa todas las filas extraídas de un procesamiento.'
|
||||
Note: 'Lote creado al iniciar una extracción; agrupa todas las filas extraídas.'
|
||||
}
|
||||
|
||||
Table extraction_rows {
|
||||
@@ -64,37 +161,6 @@ Table extraction_rows {
|
||||
Note: 'Una o más filas por radicado según flatten_extraction_result().'
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tareas asíncronas (API de extracción)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Table tasks {
|
||||
id varchar(36) [pk, note: 'UUID v4']
|
||||
type varchar(64) [not null, note: 'p. ej. extraction']
|
||||
status varchar(32) [not null, default: 'pending', note: 'pending | running | completed | failed']
|
||||
title text
|
||||
request jsonb [not null, default: '{}', note: 'Payload de la petición que originó la tarea']
|
||||
result jsonb [not null, default: '{}', note: 'Al completar incluye extraction_batch_id']
|
||||
error text
|
||||
owner_id varchar(36) [note: 'Reservado para multi-usuario']
|
||||
created_at timestamptz [not null]
|
||||
updated_at timestamptz [not null]
|
||||
started_at timestamptz
|
||||
finished_at timestamptz
|
||||
|
||||
indexes {
|
||||
type
|
||||
status
|
||||
owner_id
|
||||
}
|
||||
|
||||
Note: '''
|
||||
Cola de trabajos en segundo plano del servicio de extracción.
|
||||
No hay FK a extraction_batches; el vínculo se guarda en
|
||||
result.extraction_batch_id al finalizar la tarea.
|
||||
'''
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Limpieza
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -103,7 +169,7 @@ Table cleaning_jobs {
|
||||
id varchar(36) [pk, note: 'UUID v4']
|
||||
extraction_batch_id varchar(36) [not null, ref: > extraction_batches.id]
|
||||
status varchar(32) [not null, default: 'pending', note: 'pending | running | completed | failed']
|
||||
request jsonb [not null, default: '{}', note: 'CleaningRequest (rules_per_column, cop_mod_*, etc.)']
|
||||
request jsonb [not null, default: '{}', note: 'CleaningRequest (rules_per_column, etc.)']
|
||||
log jsonb [not null, default: '[]', note: 'Lista de mensajes de auditoría del job']
|
||||
error text
|
||||
created_at timestamptz [not null]
|
||||
@@ -130,11 +196,5 @@ Table cleaned_rows {
|
||||
extraction_batch_id
|
||||
}
|
||||
|
||||
Note: 'Salida del servicio de limpieza; reemplaza las filas previas del mismo job en cada ejecución.'
|
||||
Note: 'Salida del servicio de limpieza.'
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Relaciones lógicas (sin FK en BD)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// tasks.result.extraction_batch_id -> extraction_batches.id (referencia en JSON)
|
||||
|
||||
Reference in New Issue
Block a user