Aparência
Persistência: da mensagem às tabelas
Objetivo: continuar a leitura de prepareTelemetry. Agora a função realmente escreve no banco.
A decisão inicial
Em apps/mqtt-to-db/src/persistence.ts:
ts
if (message.ok) {
await persistValidTelemetry(database, message);
return;
}
await persistInvalidTelemetry(database, message);O trecho é real. A classificação já ocorreu no pacote MQTT. Uma mensagem inválida não pode criar dispositivo ou amostra a partir de dados rejeitados.
Caminho inválido
persistInvalidTelemetry cria apenas raw_messages, com valid: false, erro e corpo original. deviceId fica nulo. Uma operação isolada não necessita uma transação adicional para agrupar múltiplos efeitos.
Caminho válido, em uma transação
- Device é identificado pelo par type + externalId.
- Se for novo, recebe activeOnCreate; se existir, apenas lastSeenAt é atualizado.
- Cada chave passa por upsert no catálogo de métricas.
- createMany insere uma linha por métrica.
- A mensagem bruta é gravada como válida.
Se uma etapa falha, a transação desfaz o conjunto. Ela não inclui a leitura do inversor ou a entrega MQTT.
Por que o update está vazio?
ts
await transaction.metricDefinition.upsert({
where: { key: metric.key },
create: metricCreateData(metric),
update: {},
});Esse vazio é uma regra: a telemetria não deve apagar unidade, descrição ou active revisados por uma pessoa. Pelo mesmo motivo, Device existente não perde name, metadata ou active quando chegam novas mensagens.
Uma mensagem fictícia
Com duas chaves numéricas, a persistência grava duas medições e uma mensagem bruta. Mensagens posteriores reutilizam catálogo existente, mas criam novas amostras.
Não confunda upsert do catálogo com deduplicação de medições. O schema não declara uma unicidade que elimine repetições MQTT.
Verifique se entendeu
Se a gravação da mensagem bruta falhar depois de createMany, as amostras ficam salvas?
Não, no caminho válido estão na mesma transação. Isso protege coerência, não a precisão física dos valores.
Continue em fila e encerramento.
Revisão: 06/10/2026. Base: persistence.ts, message-processor.ts e schema.prisma. Trechos selecionados, não instruções para executar gravações.