fix(segments): JSONExtractString + propaga erro (EVO-1901)#86
Conversation
There was a problem hiding this comment.
Sorry @daniloleonecarneiro, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
dpaes
left a comment
There was a problem hiding this comment.
Changes requested — EVO-1901 (D12)
The mechanical rename (JSON_EXTRACT_STRING → JSONExtractString) is complete and correct, but it was applied to dead code: the edited segment-builders/* classes are reached only via SegmentBuilderFactory.createBuilder, and createBuilder / buildQuery have zero callers repo-wide (the factory is a provider injected nowhere, no test exercises buildQuery). The live segment-recompute path (modular-segment-computation.service.ts:311 → SegmentClickHouseQueryBuilder...) is untouched, so the D12 runtime failure is not fixed by this PR (AC1 unmet).
What's missing: apply the JSONExtractString fix on the actual runtime recompute path (the builder/service truly used), and add a test that exercises that live buildQuery. If the renamed builders are in fact wired somewhere I missed, point me to the call site and I'll revisit.
…ad errors (EVO-1901) Live recompute SQL is built by SegmentClickHouseQueryBuilderService (modular-segment-computation STAGE 1), which already emits the valid ClickHouse function JSONExtractString. The 28 JSON_EXTRACT_STRING occurrences were exclusively in segment-builders/* reached only via SegmentBuilderFactory.createBuilder, which has no caller anywhere in src - dead code with zero runtime effect. Remove the dead builders, the factory and their provider/export registrations so grep -rn JSON_EXTRACT_STRING src is now 0. N9: the live read methods in segment-computation.service.ts (getSegmentContacts, called by segments.service/controller, plus getContactSegments/isContactInSegment) now log ERROR and rethrow instead of returning []/false, so a ClickHouse failure is no longer indistinguishable from a genuinely empty segment. Add a test exercising the live builder (asserts JSONExtractString, never JSON_EXTRACT_STRING).
1f98779 to
53a8525
Compare
Correção do review (re-trabalho EVO-1901)O review anterior estava certo: o rename
O que mudou agora
Resultados reais
Rebase em cima de |
…e flat (EVO-1901)
Causa real do D12 (o rename JSON_EXTRACT_STRING era no-op: caminho vivo ja
usava JSONExtractString; os builders deletados eram codigo morto).
O builder vivo (segmentNodeToStateSubQuery) extraia custom attribute como
chave top-level: JSONExtractString(traits, '<attr>') (comentava 'campo direto,
nao aninhado'). Mas a ingestao grava o atributo como DELTA event
(contact.custom_attribute.changed com { attributeName, attributeValue,
changeType }) e tambem aninhado em traits.customAttributes.<attr> nos
snapshots contact.updated — nunca como chave flat. Logo a condicao casava 0
eventos e segmentos com condicao computavam 0 membros (D12).
Fix: quando o path e customAttributes.<attr>, a condicao seleciona os eventos
de mudanca do atributo (event_name = 'contact.custom_attribute.changed' AND
attributeName = '<attr>') e o argMaxValue pega o ultimo attributeValue
(changeType 'removed' zera). generateArgMaxValidation aplica o operador/valor
sobre esse valor — mesma abordagem por-atributo que o builder morto usava.
Verificado contra ClickHouse com dados reais do e2e: tier==platinum casa só o
contato platinum; tier==gold casa só o gold. tsc limpo (so 4 TS2393
pre-existentes em clickhouse.service.ts, regressao da develop #87/#101).
jest live-path: 2/2.
Respondendo ao review do D12 — causa real encontrada + fix aplicado (commit
|
| Extração | Contatos distintos |
|---|---|
JSONExtractString(traits,'tier') (o que o builder gerava) |
0 |
delta: argMax(attributeValue) WHERE attributeName='tier' |
2 (corretos) |
O path aninhado simples também falha sob argMax porque o último evento do contato costuma ser um delta sem customAttributes.
Fix (commit 359fcb3)
No caso customAttributes.<attr> do builder vivo, a condition passa a selecionar os eventos de mudança (event_name = 'contact.custom_attribute.changed' AND attributeName = '<attr>') e o argMaxValue pega o último attributeValue (changeType='removed' zera). É a mesma abordagem por-atributo que o builder morto usava (ele estava certo no shape, errado na função). generateArgMaxValidation aplica o operador/valor sobre esse valor.
Validação end-to-end (membership gerado contra o ClickHouse real): tier==platinum → casa só o contato platinum; tier==gold → casa só o gold. tsc limpo (só os 4 TS2393 pré-existentes de clickhouse.service.ts, regressão da develop #87/#101). jest live-path 2/2 (inclui novo teste travando o delta).
A parte do N9 segue como estava (aprovada). Resumo: D12 foi mal-diagnosticado quanto ao mecanismo (nome da função/código morto), mas o sintoma era real e agora está corrigido no caminho vivo.
dpaes
left a comment
There was a problem hiding this comment.
Requesting changes. The pivot is right and the round-1 homework is done — you proved the JSON_EXTRACT_STRING→JSONExtractString rename was on dead code, found the real live custom-attribute defect (flat traits key that ingestion never writes → 0 members), fixed it to read the contact.custom_attribute.changed delta stream, removed the dead segment-builders graph (−827), and made the N9 read catches propagate. The dotted-path branch + dead-code removal look solid and the branch is CLEAN.
Two requirements before approval:
1. Sibling custom-attribute branch still broken. segment-clickhouse-query-builder.service.ts:114-121 (path==='customAttributes' + operator.value) does NOT set isCustomAttribute and still builds the flat JSONExtractString(traits,'customAttributes.<value>') — the same 0-members defect the fixed branch (:122-133 / :285-302) closes. Your e2e only exercised the dotted path (path='customAttributes.<attr>'). Either (a) apply the same delta-read (set isCustomAttribute, read contact.custom_attribute.changed) on this branch too, or (b) show with evidence that the FE never serializes a custom-attr node as path='customAttributes' + operator.value (only the dotted form) — and if so, guard it so it can't silently regress.
2. N9 propagation has no passing test. segment-computation.service.ts:280/307/338 now throw, which is correct per the AC, but there's no spec proving it and one can't compile today: develop's clickhouse.service.ts has duplicate ensureKafkaEngineBroker/extractKafkaBrokers (TS2393), which SegmentComputationService imports transitively. Please add a propagation spec; it likely requires un-blocking that TS2393 duplicate first (worth its own card — your call). Code-only verification isn't enough here given evo-flow runs no jest/tsc in CI.
Non-blocking (for later): user-configurable segment fields are interpolated unescaped into ClickHouse SQL (:286 etc.) — pre-existing systemic pattern in the live builder, worth a hardening card.
Card moved to Todo. Ping me when both are addressed and I'll re-review.
Resumo
Defeito D12 + N9 do e2e de jornadas (trigger de segmento).
JSON_EXTRACT_STRING(...)(estilo MySQL/Postgres), que não existe no ClickHouse — o correto éJSONExtractString(...). Trocadas as 28 ocorrências nos 6 builders afetados (channel, custom-attribute, email, user-property, performed, label). Com isso a query parava de lançarFunction with name 'JSON_EXTRACT_STRING' does not existe o segmento volta a computar os membros corretos (antes: 0 silencioso).segment-computation.service.ts(getSegmentContacts,getContactSegments,isContactInSegment) logavam mas retornavam[]/false, transformando falha de ClickHouse em "contato em nenhum segmento" indistinguível de vazio real. Agora logam e propagam o erro.Arquivos
src/modules/segments/services/segment-builders/{channel,custom-attribute,email,user-property,performed,label}-segment-builder.tssrc/modules/segments/services/segment-computation.service.tsTest plan
npx jest src/modules/segments→ 3 suites, 10 testes verdes.tsc --noEmitlimpo.grep JSON_EXTRACT_STRING→ 0 ocorrências restantes.EVO-1901