PR#1 (C): escrita falha LOUD em vez de no-op silencioso (rebased no main)#529
PR#1 (C): escrita falha LOUD em vez de no-op silencioso (rebased no main)#529adm01-debug wants to merge 1 commit into
Conversation
…atual (#524) Rebase sobre o main atual (inclui #526, telemetria recordBridgeCall) para eliminar o conflito do #524. Branch recriada a partir do main + este \u00fanico commit. - WRITE_OPERATIONS + isWriteOperation + WriteUnavailableError (novos).\n- invokeExternalDb: escrita com bridge OFF/kill-switch/CORS agora THROW (ap\u00f3s reportSilentEmpty + recordCall + recordKillSwitchHit do #526); leitura segue retornando vazio.\n- invokeExternalDbDelete: THROW em vez de no-op silencioso.\n- index.ts: exporta WriteUnavailableError e isWriteOperation. Toda a telemetria do #526 preservada (7x recordCall). tsc --noEmit limpo. Escopo do PR#1 = apenas bridge.ts + index.ts (rest-native writes + testes ficam no PR#2/#525).
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
Warning Review limit reached
More reviews will be available in 31 minutes and 21 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
Este PR ajusta a camada external-db para evitar corrupção silenciosa quando a bridge está OFF/inacessível: operações de escrita passam a falhar LOUD (lançando erro tipado) em vez de retornarem {records: [], count: 0} sem persistir, preservando o comportamento “vazio” apenas para leituras.
Changes:
- Adiciona
WriteUnavailableError(erro tipado) e helperisWriteOperation()para distinguir operações de escrita. - Em
invokeExternalDb, quando bridge está OFF / kill-switch ativo / erro de CORS/rede: writes lançam erro (reads seguem retornando vazio), mantendo emissão de telemetria antes do throw. - Em
invokeExternalDbDelete,KillSwitchActiveErrore CORS/rede deixam de ser no-op silencioso e passam a lançar.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/lib/external-db/bridge.ts | Introduz WriteUnavailableError + roteamento/erros “LOUD” para writes quando bridge OFF/kill-switch/CORS, e ajusta delete para não ser no-op silencioso. |
| src/lib/external-db/index.ts | Re-exporta isWriteOperation e WriteUnavailableError no barrel do módulo. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const WRITE_OPERATIONS: ReadonlySet<Operation> = new Set<Operation>([ | ||
| 'insert', | ||
| 'update', | ||
| 'delete', | ||
| 'upsert', | ||
| 'batch_insert', | ||
| ]); | ||
|
|
||
| /** True para qualquer operação que MUTA dados (tudo menos 'select'). */ | ||
| export function isWriteOperation(op: Operation | string | undefined): boolean { | ||
| return !!op && WRITE_OPERATIONS.has(op as Operation); | ||
| } |
| if (err instanceof KillSwitchActiveError) { | ||
| logger.warn(`[external-db] Delete blocked by kill-switch for ${table}/${id}`); | ||
| return; | ||
| // Delete não pode no-op silencioso: a UI mostraria "excluído com sucesso" | ||
| // sem nada ter sido removido. Vira toast.error no caller. | ||
| logger.warn(`[external-db] Delete blocked by kill-switch for ${table}/${id} — surfacing loud`); | ||
| throw new WriteUnavailableError(table, 'delete'); |
…E + testes Re-land do PR#2 (estava órfão após o rebase do #524/#529). rest-native.ts = main atual (telemetria #526 intacta) + seção WRITE (Plano A) anexada: executeRestNativeWrite/tryExecuteRestNativeWrite/isRestNativeWriteEligible com as 6 guardas (A1 RLS, A2 anti-mutação-em-massa, A3 tabela base nunca view, A4 select-back vazio=sucesso, A5 remap EN→PT, sem retry/LOUD). + rest-native-write.test.ts (12 casos).
Substitui o #524 (a branch foi rebaseada sobre o
mainatual para eliminar o conflito com o #526 — telemetriarecordBridgeCallno caminho vivo). Conteúdo idêntico ao planejado para o PR#1, agora sem conflito.Contexto
Bridge OFF (
edge_external_db_bridge:enabled=false, rollout=100→ REST nativo 100%) +rest-nativecobrindo só SELECT = toda ESCRITA retornava{records:[],count:0}silenciosamente. A UI dizia "salvo/excluído com sucesso" sem persistir — corrupção silenciosa.Mudanças (apenas
bridge.ts+index.ts)WriteUnavailableError(tipado) + helperisWriteOperation().invokeExternalDb: escrita com bridge OFF / kill-switch / CORS agora lança em vez de retornar vazio. Leitura mantém vazio (REST nativo é o caminho real).invokeExternalDbDelete: lança em vez dereturnsilencioso.reportSilentEmpty('write_bridge_off')+ telemetria do feat(external-db): Etapa 2 — telemetria no caminho vivo (recordBridgeCall) #526 (recordCall/recordKillSwitchHit) preservados antes do throw.index.tsexporta os novos símbolos.Conflito resolvido
O #526 entrou no
maine instrumentoubridge.tsnas mesmas regiões. Esta branch foi recriada a partir domainatual + 1 commit com o merge correto (toda a telemetria do #526 intacta — 7×recordCall— e o LOUD do PR#1 em regiões distintas).git merge-treecontra omain: limpo.Validação
tsc --noEmit: 0 erros. Escopo do PR#1 = sóbridge.ts+index.ts; escrita REST nativo + testes ficam no PR#2 (#525).Série: #1 (C) → #2/#3 (A: escrita REST nativo + RLS) → #4 (aposentar bridge).
Summary by cubic
Impede no-ops silenciosos em ESCRITAS no external DB: quando a bridge está OFF, o kill-switch ativa, ou há erro de CORS/rede, operações de escrita agora lançam
WriteUnavailableError. Evita “salvo/excluído com sucesso” sem persistir.invokeExternalDb: para escritas, lança em vez de retornar{records:[],count:0}em bridge OFF/kill-switch/CORS; leituras seguem retornando vazio.invokeExternalDbDelete: lança nas mesmas condições, removendo no-op silencioso.reportSilentEmpty,recordCall,recordKillSwitchHitsão registrados antes do throw.isWriteOperationeWriteUnavailableErroradicionados e exportados porindex.ts.Written for commit 6c7585d. Summary will update on new commits.