Conversation
…ebhook ingestion The webhook ingestion looked the duplicate sale up by external_order_id within the company, backed by a unique index on (company_id, external_order_id). Two channels of the same company number their sales on their own, so when a second channel sent an id the first had already used, the sale was taken for a duplicate: the log ended processed with no order, no units taken and nothing in the dead letter queue. The sale was lost without a signal. The same sale is now the same id in the same channel: the lookup, the model validation and the unique index are scoped to company_integration_id, which already implies the company. Manual orders cannot carry an external id, so the null integration leaves nothing uncovered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
Revisado. Lo veo bien para implementar. El diagnóstico es correcto y es un problema de diseño, no un descuido: cada canal numera sus ventas por su lado, así que Lo que verifiqué
Antes de mergear
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket de Jira
https://proyectofinalfrlp.atlassian.net/browse/TESIS-999020
Descripción
La ingesta de webhooks buscaba la venta duplicada con
Order.find_by(external_order_id:)—acotado sólo por tenant— y el respaldo era un índice único(company_id, external_order_id). Pero cada canal numera sus ventas por su lado: si una empresa tiene Mercado Libre y Tiendanube y el segundo manda un id que el primero ya usó, la venta se tomaba por duplicada. El log quedabaprocessed, no se creaba la orden, no se descontaba stock y no quedaba nada en la DLQ: la venta se perdía sin ninguna señal.Repro en
master: ML ingiere el id5001(2 unidades) y después TN ingiere el5001(3 unidades) → los dos logsprocessed, una sola orden, stock 18 (se descontaron sólo 2),FailedEvent.count == 0.Decisiones que conviene mirar:
La misma venta es el mismo id en el mismo canal. La búsqueda (
already_registered), la validación del modelo y el índice único pasan acompany_integration_id+external_order_id. La integración ya implica la empresa (cada una es de una sola), así que el aislamiento entre tenants no cambia.El NULL de la integración no deja huecos. Las órdenes manuales no pueden llevar id externo (
ORDER_FIELDSno lo permite), y todas las que entran por webhook traen su integración. No hace faltaNULLS NOT DISTINCT.La migración no puede fallar con datos existentes. Todo lo que era único por empresa también lo es por integración.
schema.rb: para no migrar la base de desarrollo compartida, tomé el volcado real de la base de test después de migrar y apliqué sólo las dos líneas de este cambio (versión e índice). El resto del volcado difería en el formato de los CHECK por la versión local de Postgres.ScopeOrderExternalIdToIntegration(timestamp real, sin duplicados contramaster).Orders::ProcessWebhookOrder#already_registeredyORDERS_UNIQUE_INDEXapuntan al índice nuevo; el rescate de la carrera entre dos workers usa la misma búsqueda.Ordervalida la unicidad del id externo por integración.Evidencia visual
N/A
Cómo probar
Precondición:
bin/rails db:migrate.5001→ se crea la orden.5001→ se crea otra orden, de TN, y descuenta su stock. Enmasterse descarta en silencio.Verificación:
bundle exec rspec(1570 ejemplos, 0 fallas, cobertura 99.89% de línea),rubocopybrakemanlimpios.Dientes: con la búsqueda por empresa, fallan los 2 specs nuevos de la ingesta.
Impacto y consideraciones
¿Introduce breaking changes?
No para los clientes. Cambia un índice único (migración reversible).
¿Requiere nuevas variables de entorno?
No
¿Afecta la arquitectura o genera un nuevo patrón?
Ajusta la clave de idempotencia de ADR-010 (de empresa a canal); el ADR queda actualizado en este PR.
Conflictos esperables: con proyecto-api#104 (misma clase, otra zona) y con cualquier rama que agregue migraciones (la línea de versión de
schema.rb).🤖 Generated with Claude Code