deletion-inventory.service.js
Overview
Este módulo implementa un inventario de solo lectura para el estado de las eliminaciones de Requirements D-09. Reúne evidencia de Listing, Conversation, User y MediaFileClaim, y delega la decisión final a deletion-inventory.classify.js.
El flujo está dividido en cuatro secciones: requirements, claims, conversations y shared. DEFAULT_SECTIONS ejecuta solo las tres primeras, y shared queda como sección opcional. El generador emite candidatos, errores y un resumen final. fileciteturn1file0turn1file9
[!IMPORTANT] Las pruebas de MongoDB real y la guardia estática confirman que este archivo no ejecuta escrituras, no usa
$mergeni$out, y no llama a ImageKit. fileciteturn1file2turn1file4
How it works
El punto de entrada es runDeletionInventory. Valida la configuración, prepara el contexto común y ejecuta las secciones pedidas en orden. Cada sección pagina por _id, limita el tiempo de consulta con maxTimeMS, clasifica el resultado y lo emite como registro normalizado. fileciteturn1file9turn1file16
flowchart TD
Start[runDeletionInventory] --> Validate[Validate options]
Validate --> Build[Create ctx and summary]
Build --> Req[requirementsSection]
Build --> Clm[claimsSection]
Build --> Cnv[conversationsSection]
Build --> Shr[sharedSection]
Req --> ReqFind[Listing find pending requirements]
ReqFind --> ReqEvidence[readEvidence]
ReqEvidence --> ReqClass[classifyPendingRequirement]
ReqClass --> Emit[Yield record]
Clm --> ClmFind[MediaFileClaim find claims]
ClmFind --> ClmEvidence[readEvidence]
ClmEvidence --> ClmClass[classifyMediaClaim]
ClmClass --> Emit
Cnv --> CnvAgg[Conversation aggregate with lookup]
CnvAgg --> CnvClass[classifyConversationReference]
CnvClass --> CnvEmit[Skip valid references or yield record]
Shr --> ShrAgg[Listing aggregate shared files]
ShrAgg --> ShrClass[classifySharedFile]
ShrClass --> ShrEmit[Yield record]
Emit --> Summary[Update summary]
CnvEmit --> Summary
ShrEmit --> Summary
Summary --> End[Yield final summary]
El flujo usa helpers pequeños para mantener el comportamiento predecible. record normaliza la salida, readEvidence aísla fallos por subconsulta, y errorCode evita exponer el mensaje completo del error. fileciteturn1file8turn1file16
Key components
Estos son los componentes principales del archivo. El módulo es funcional, pero su trabajo está separado en helpers internos y un generador exportado. fileciteturn1file9turn1file16
{
"title": "runDeletionInventory",
"content": "Generador asincrono exportado que valida opciones, ejecuta las secciones seleccionadas, emite candidatos y errores, y termina con un resumen global.",
"type": "function",
"filePath": "services/api/src/modules/reconciliation/deletion-inventory.service.js",
"badges": [
"public"
]
}
{
"title": "requirementsSection",
"content": "Recorre Listings con intent requirement y deletion.status pending. Relee owners, conversaciones activas, reservas, adjuntos pendientes, claims y stillPending para clasificar Requirements pendientes.",
"type": "function",
"filePath": "services/api/src/modules/reconciliation/deletion-inventory.service.js",
"badges": []
}
{
"title": "claimsSection",
"content": "Recorre MediaFileClaim por _id. Cruza la claim con su Listing, calcula la identidad persistida del archivo y busca referencias desde otros Listings.",
"type": "function",
"filePath": "services/api/src/modules/reconciliation/deletion-inventory.service.js",
"badges": []
}
{
"title": "conversationsSection",
"content": "Recorre Conversations con activeRequirementId. Hace lookup al Listing objetivo, clasifica la referencia y omite las referencias v\u00e1lidas sin emitir candidato.",
"type": "function",
"filePath": "services/api/src/modules/reconciliation/deletion-inventory.service.js",
"badges": []
}
{
"title": "sharedSection",
"content": "Detecta archivos compartidos por varios Listings usando agregaci\u00f3n. Solo informa presencia de compartici\u00f3n y no prueba ausencia de otras referencias.",
"type": "function",
"filePath": "services/api/src/modules/reconciliation/deletion-inventory.service.js",
"badges": []
}
{
"title": "readEvidence",
"content": "Ejecuta lecturas de evidencia una por una. Si una lectura falla, devuelve null para ese bloque y agrega un registro error.",
"type": "function",
"filePath": "services/api/src/modules/reconciliation/deletion-inventory.service.js",
"badges": []
}
Data & fields
El archivo define constantes de ejecución, una forma estándar de registro y un resumen final con estadísticas por sección. También expone datos de apoyo para construir evidencia mínima y segura. fileciteturn1file0turn1file9turn1file16
Constantes de ejecución
INVENTORY_SCHEMA_VERSION[badge:read-only]number— Versión del esquema del inventario. Su valor es1.INVENTORY_SECTIONS[badge:read-only]string[]— Secciones válidas:requirements,claims,conversations,shared.DEFAULT_SECTIONS[badge:read-only]string[]— Secciones por defecto:requirements,claims,conversations. No incluyeshared.DEFAULT_BATCH_SIZE[badge:read-only]number— Tamaño de lote por defecto. Su valor es200.MAX_BATCH_SIZE[badge:read-only]number— Límite superior permitido parabatchSize. Su valor es1000.DEFAULT_LIMIT[badge:read-only]number— Límite total por defecto. Su valor es10_000.DEFAULT_MAX_TIME_MS[badge:read-only]number— Tiempo máximo por consulta. Su valor es30_000.
Entrada de runDeletionInventory
[
{
"name": "sections",
"type": "string[]",
"description": "Secciones a ejecutar. Valores válidos: requirements, claims, conversations y shared."
},
{
"name": "batchSize",
"type": "number",
"description": "Tamaño de lote por página. Debe estar entre 1 y 1000."
},
{
"name": "limit",
"type": "number",
"description": "Límite total de candidatos a revisar por ejecución. Debe ser positivo."
},
{
"name": "maxTimeMS",
"type": "number",
"description": "Tiempo máximo aplicado a cada consulta de base de datos."
},
{
"name": "hooks",
"type": "object",
"description": "Callbacks opcionales para pruebas entre lecturas."
},
{
"name": "now",
"type": "Date",
"description": "Marca temporal base usada para ageSeconds y observedAt."
}
]
Registro emitido por las secciones
kind[badge:required]string— Tipo de registro. Puede serrequirement_pending,media_claim,conversation_reference,shared_file,errorosummary.id[badge:required]string— Identificador principal del candidato o del error.related[badge:required]object— Relación mínima con otros identificadores.observed[badge:required]object— Estado observado en el momento del inventario.evidence[badge:required]array— Lista de fragmentos de evidencia concodeyvalue.classification[badge:required]string— Clasificación devuelta por el clasificador puro.reasonCode[badge:required]string— Código de razón de la clasificación.suggestedAction[badge:required]string— Acción sugerida por el clasificador.requiresApproval[badge:required]boolean— Indica si la acción requiere aprobación.authorizesExecution[badge:required]boolean— Indica si la salida autoriza ejecución automática.ageSeconds[badge:optional]number | null— Antigüedad derivada derequestedAtoupdatedAt.observedAt[badge:required]string— Marca ISO del momento de observación.
related.ownerId— Dueño del Requirement o de la Conversation.related.listingId— Listing asociado a unaMediaFileClaim.related.requirementId— Requirement activo asociado a una Conversation.related.listingIds— Listings que comparten un archivo.observed.deletionStatus— Estado de eliminación observado enListing.observed.attempts— Intentos de eliminación observados enListing.observed.publicationStatus— Estado de publicación observado.observed.lifecycleStatus— Estado de ciclo de vida observado.observed.accountStatus— Estado de cuenta del dueño, cuando existe.
Resumen final
El último valor emitido por runDeletionInventory es un objeto de summary. Guarda el estado global de la corrida y las estadísticas por sección.
kind[badge:required]string— Siempresummary.schemaVersion[badge:required]number— Versión del esquema de inventario.observedAt[badge:required]string— Marca ISO de inicio de la corrida.sections[badge:required]object— Estadísticas por sección ejecutada.failed[badge:required]boolean—truesi alguna sección registró errores.
Cada sección usa una forma base común.
scanned— Documentos recorridos en páginas.emitted— Registros emitidos por la sección.limitReached— Indica que la sección cortó por el límite configurado.errors— Cantidad de errores acumulados.classifications— Conteo por valor declassification.
Algunas secciones agregan campos propios.
conversations.validReferences— Cuenta referencias válidas que no se emiten.shared.presenceOnly— Marca que la sección solo informa presencia de compartición.
Behaviors
El archivo contiene helpers pequeños y funciones de sección con responsabilidades muy concretas. Todas mantienen el estilo de solo lectura del módulo. fileciteturn1file8turn1file10turn1file16
Helpers
step(hooks, name)— Ejecuta un hook de prueba si existe. No afecta la lógica productiva.errorCode(error)— Normaliza el código del error y recorta el resultado a 64 caracteres. Nunca usa el mensaje completo.ageSeconds(date, now)— Calcula la antigüedad en segundos cuando recibe unDate. Devuelvenullen otros casos.imageKitFileIdsOf(listing)— ExtraefileIddemediaconprovider = "imagekit"y desourceDocuments.referencedFileIds(listing)— Devuelve unSetcon todos losfileIdreferenciados pormediaysourceDocuments.record(...)— Construye la forma común de salida. Copia los campos de la decisión y añadeageSecondsyobservedAt. fileciteturn1file8turn1file16readEvidence(section, readers, errors)— Ejecuta varias lecturas de evidencia. Cada fallo agrega un error y deja ese bloque ennull.newStats()— Crea el acumulador base de una sección.count(stats, item)— Incrementaemittedy acumula la clasificación emitida.
requirementsSection
- Filtra
Listingconintent: "requirement"ydeletion.status: "pending". - Paginiza por
_idy usa proyección mínima. - Reúne
owners,refs,reservations,attach,claimsystillPending. - Relee
stillPendingal final del lote para detectar cambios durante la lectura. - Clasifica con
classifyPendingRequirement. fileciteturn1file0turn1file18
claimsSection
- Lee
MediaFileClaimpor_idy proyectalistingId,state,holderyupdatedAt. - Busca el
Listingdueño y los Listings que referencian el archivo. - Usa
persistedFileIdentity(listing, claim._id).presentpara comprobar identidad persistida. fileciteturn1file0turn1file9 - Construye evidencia con
listingyreferences. - Clasifica con
classifyMediaClaim. fileciteturn1file0turn1file18
conversationsSection
- Lee
ConversationconactiveRequirementIdno nulo. - Usa
Conversation.aggregatecon$lookuphaciaListing. - Construye evidencia sobre el target, el intent, la propiedad compartida y el estado de eliminación.
- Si la decisión es
VALID_REFERENCE, incrementavalidReferencesy no emite candidato. fileciteturn1file1turn1file18 - En otros casos, emite un
conversation_reference.
sharedSection
- Usa una agregación de
ListingconallowDiskUse: true. - Calcula la unión de
media.fileIdysourceDocuments.fileId. - Agrupa por archivo y conserva solo los que aparecen en más de un Listing.
- Marca
presenceOnly = true. Ese dato solo prueba compartición presente. No prueba ausencia de otras referencias. fileciteturn1file10turn1file1 - Clasifica con
classifySharedFile.
runDeletionInventory
- Valida que las secciones existan en
INVENTORY_SECTIONS. - Valida que
batchSizeesté entre1yMAX_BATCH_SIZE. - Valida que
limitsea un entero positivo. - Construye
ctxconobservedAtcalculado desdenow. - Ejecuta cada sección en el orden pedido.
- Marca
failed = truesi alguna sección registra errores. - Emite un
summaryfinal al terminar.
Workflows
La ejecución real sigue una secuencia corta y determinista. El diseño busca acotar memoria y limitar el alcance de cada lote. fileciteturn1file0turn1file16
1. Validar configuración | Comprueba secciones, batchSize y limit antes de iniciar.
2. Preparar contexto | Crea ctx con observedAt, now, maxTimeMS y hooks.
3. Recorrer secciones | Ejecuta requirements, claims, conversations y shared, si fueron solicitadas.
4. Leer evidencia | Hace consultas mínimas y maneja fallos por bloque de evidencia.
5. Clasificar y emitir | Convierte la evidencia en registros normalizados.
6. Cerrar corrida | Emite un summary con estadísticas y marca failed si hubo errores.
Gotchas & edge cases
El archivo contiene varias reglas de control de fallos. Todas están documentadas en el código y en las pruebas de integración. fileciteturn1file0turn1file2
[!WARNING] Si una lectura de evidencia falla, el bloque afectado queda en
nully se agrega un registroerror. Los candidatos de ese bloque pueden salirUNRESOLVED. fileciteturn1file8turn1file18
[!WARNING] Si falla la consulta de página, la sección se detiene de inmediato. No intenta continuar con el siguiente lote. fileciteturn1file8turn1file10
[!NOTE] No hay aislamiento de instantánea entre colecciones. El archivo relee
stillPendingal final del lote y cruza lecturas en claims. Las contradicciones se clasificanVERIFY_FIRST. fileciteturn1file0turn1file18
[!NOTE]
sharedSectionsolo informa compartición observada. Un resultado parcial nunca prueba que un archivo no tenga otras referencias fuera del lote. fileciteturn1file1turn1file10
[!CAUTION]
limitpuede cortar la ejecución antes de revisar todos los candidatos. En ese caso,limitReachedqueda entrue. fileciteturn1file9turn1file10
[!TIP]
DEFAULT_SECTIONSomiteshared. Esa sección solo corre si se pide explícitamente.
Related
Este módulo se conecta con piezas puras y con lecturas de modelo muy concretas. No expone rutas HTTP, y su salida está pensada para consumo interno. fileciteturn1file0turn1file9
services/api/src/modules/reconciliation/deletion-inventory.classify.js— Contiene los clasificadores puros que deciden la salida final. El archivo los importa pararequirements,claims,conversationsyshared. fileciteturn1file0turn1file1turn1file18services/api/src/modules/conversations/requirement-association.service.js— AportacountReservationsForRequirementsycountPendingAttachForRequirements. El inventario los usa enrequirementsSection.services/api/src/modules/reconciliation/erasing-claim-evidence.js— AportapersistedFileIdentity. El inventario lo usa para validar claims. fileciteturn1file0turn1file9services/api/src/models/Listing.js— Fuente principal para Requirements, referencias compartidas y targets de conversación. fileciteturn1file0turn1file10services/api/src/models/Conversation.js— Fuente principal para referencias activas de Requirements. fileciteturn1file0turn1file1services/api/src/models/User.js— Fuente para estado de cuenta del owner en Requirements.services/api/src/models/MediaFileClaim.js— Fuente para claims y sus estados. fileciteturn1file0turn1file18services/api/integration/mongo/e6-1-deletion-inventory.mongo.js— Prueba de integración sobre MongoDB real. Verifica clasificaciones, paginación, concurrencia y cero escrituras.services/api/test/e6-1-inventory-static.test.js— Guardia estática que confirma ausencia de escrituras,$mergey$out.