Todas as publicações

Uma tela em branco é uma pergunta

Por Event Horizon Data
engineeringproduct

Isto começou com uma observação incómoda sobre o nosso próprio produto: continua a ser preciso ser técnico para construir um workflow aqui.

É uma coisa difícil de notar numa ferramenta cujo marketing diz "sem scripts". A afirmação era verdadeira. Também era incompleta, porque a versão honesta era "sem scripts, e com um analista", e a segunda metade não estava escrita em lado nenhum.

Por isso, antes de mudar seja o que for, escrevemos o que era mesmo preciso para pôr um evento no armazém. Cinco passos. E o que valeu a pena escrever não foi o número.

Nenhuma das perguntas era sobre os dados deles

O passo dois pedia à pessoa que declarasse um esquema: nomear cada coluna e, para cada uma, decidir se é uma métrica, uma dimensão, uma dimensão histórica, ou a chave que identifica uma entidade ao longo do tempo. Doze decisões, num formulário em branco, antes de ver uma única linha dos seus próprios dados.

O passo três largava-a numa tela vazia com uma paleta de nós de origem e nenhuma indicação de qual era o dela. O passo quatro fazia as mesmas perguntas de modelação do passo dois, outra vez, noutro formato.

Repare no que essas perguntas são. Métrica ou dimensão é uma pergunta sobre o nosso modelo de armazenamento. Qual dos dez nós de origem é uma pergunta sobre a nossa arquitetura de ingestão. Que um armazém precisa de um loader ao fim é uma pergunta sobre o nosso motor. Nenhuma delas é sobre os dados do cliente, que é a única coisa com que ele chegou e a única em que é especialista.

Uma tela em branco parece liberdade. É uma pergunta, e nós fazíamos três antes da primeira que servia para alguma coisa.

Recomendar, e depois esperar

A primeira correção foi inverter o passo dois: em vez de pedir a alguém que descreva os seus dados, deixá-lo colar um evento e descrevermos-lhos nós.

Números viram métricas. Texto vira dimensões. Uma data vira candidata a coluna de tempo. Cada proposta traz a razão pela qual foi feita, ao lado do valor real que a produziu.

A decisão que mais importa aqui é o que ele não faz: nunca cria o bucket. Propõe e espera.

Duas razões, e a segunda é a que interessa. Um esquema errado criado em silêncio é caro de desfazer, porque a partir desse momento há dados escritos contra ele. E o passo da confirmação é onde alguém aprende o modelo sem ser mandado para formação. Vê revenue proposto como métrica ao lado do número que enviou de facto, e a classificação deixa de ser vocabulário nosso e passa a ser óbvia.

O endpoint por trás é puro. Recebe uma amostra, devolve colunas propostas, e não escreve absolutamente nada. Quem escreve continua a ser a mesma chamada de criação de sempre, com o esquema que a pessoa confirmou.

A tela, e as dez portas

O passo três eram dois problemas vestidos com um casaco só.

O primeiro era o vazio. Um workflow novo abre agora com uma origem e um loader já ligados, porque o destino de um nó de origem numa tela vazia é sempre o armazém. É um passo que só se salta sabendo a arquitetura, e era onde as pessoas ficavam presas sem saber que tinham ficado.

O segundo problema era mais difícil, e ao início percebemos-lhe mal a forma. Dez nós de origem numa lista não dizem nada sobre qual é o seu. cdc_node e db_reader_node são ambos "uma base de dados". webhook_node, http_node e probe_node são todos "uma API". Escolher entre eles é, outra vez, uma pergunta sobre nós.

Por isso a tela oferece agora as formas que as pessoas têm de facto, na linguagem delas: alguém chama-nos, uma base de dados minha, uma API que consultamos, ficheiros numa pasta. Escolher uma monta a cadeia inteira, ligada, com todos os campos no seu próprio valor por omissão. Não configura nada, porque a connection e o bucket são decisões sobre os dados deles, e essa metade nunca devemos adivinhar.

A parte em que nos enganámos

Depois veio a pergunta óbvia seguinte. E quem tem um ficheiro no computador e mais nada? Sem servidor de FTP, sem base de dados que possamos seguir, sem API. Só um CSV.

A proposta em cima da mesa foi uma importação direta. Carregar o ficheiro no ecrã do bucket, inferir o esquema a partir dele, carregar as linhas. Sem workflow, sem tela, sem nós. Era o caminho mais curto entre "tenho um ficheiro" e "tenho um dashboard", e foi defendida com alguma convicção.

Era a resposta errada, e a correção foram duas frases: a porta de entrada é sempre o ingestor, e o ficheiro pode nem ser um CSV, pode ser algo que tem de ser trabalhado.

A proposta tinha sido desenhada para o caso feliz. Um CSV arrumado é o caso fácil, e uma porta construída à volta dele teria sido um segundo caminho de escrita para o armazém que salta o parser, o transformer, o filtro, o validador e a verificação de esquema. O primeiro ficheiro que não fosse um CSV arrumado teria obrigado a construir tudo isso outra vez, do outro lado, no sítio onde já existia.

Por isso o ficheiro entra pela mesma porta que todo o resto. Carrega-se, e entra no pipeline como bytes em bruto, exatamente como entra um ficheiro trazido por SFTP, e tudo o que vem a seguir já sabe o que fazer com ele. Construir a porta custou uma fração do que teria custado o atalho, porque quase nada era novo.

Não ficamos com o ficheiro

Mais uma decisão, e é a que tem uma consequência que vale a pena explicar em vez de anunciar.

O ficheiro carregado nunca é escrito em disco. Nem no servidor da aplicação, nem em armazenamento de objetos, nem no bus de mensagens que leva os registos entre as fases do pipeline. Existe em trânsito e na memória de um worker, e depois desaparece.

A história da privacidade é a parte fácil. Não há uma segunda cópia dos dados de um cliente a viver algures à espera de ser apagada, e nenhum upload aparece em inventário de retenção nenhum.

A parte incómoda é o que isso custa. Uma origem de SFTP pode ir buscar o ficheiro outra vez. Um webhook pode contar com o chamador a repetir. Um upload perdido entre o nosso "recebido" e o pipeline não é recuperável por ninguém, porque a única cópia estava em memória.

A regra que resolve isso sem guardar nada: não responder "aceite" antes de o lote estar mesmo entregue ao pipeline. A cópia durável passa a ser a do próprio cliente, no disco dele. Qualquer coisa que não seja sucesso é repetida por ele, e a repetição é inofensiva.

O que isto proíbe é a forma instintiva de fazer uploads, que é aceitar o ficheiro, responder já, e processar depois. Aqui isso transformaria "não guardamos" em "perdemos em silêncio", e são promessas muito diferentes.

O que as três barreiras tinham em comum

Tecnicamente, nada. Uma era um formulário, outra uma tela, outra uma lista. O que partilhavam é que cada uma pedia à pessoa que soubesse algo sobre o nosso sistema antes de o sistema a ajudar com o dela.

Simplicidade, afinal, não é um produto mais pequeno. Todos aqueles nós continuam a existir, e são 22. É a disciplina de não fazer da primeira pergunta uma pergunta sobre nós próprios.