Na Sardine, usamos protocol buffers (protobuf) em todos os lugares. É um formato de serialização leve, neutro em relação à linguagem e com tipagem.
Usamos o protobuf para definir o esquema de dados da tabela do BigQuery e também para gerar o código do servidor backend (em go) a partir do mesmo arquivo protobuf. Nossos servidores backend preenchem a struct do golang (gerada a partir do protobuf), enviam para o pubsub e, em seguida, os jobs do dataflow os capturam no BigQuery.

Esse padrão simples funcionou muito bem, com uma ressalva. Quando começamos, não havia uma solução clara sobre como converter um objeto do pubsub em uma inserção de linha no BigQuery, então precisávamos escrever código repetitivo como o abaixo para copiar dados de um objeto para outro:
TableRow clientMetadataRow = new TableRow() .set("session_key", clientMetadata.getSessionKey()) .set("client_id", clientMetadata.getClientId()) .set("revision", clientMetadata.getRevision()) .set("user_id", clientMetadata.getUserId())...
Isso era muito tedioso e propenso a erros. Quando adicionávamos um novo campo na tabela do BigQuery, também precisávamos atualizar o código repetitivo acima. Devia haver uma solução melhor para isso.
(nota lateral: se você começar um novo serviço hoje, poderia usar JSON em vez de protobuf como formato de serialização para o pubsub, e então usar o template oficial de job pubsub-to-bigquery do Google (beta) —https://cloud.google.com/dataflow/docs/guides/templates/provided-streaming)
Descobrimos que é possível iterar dinamicamente sobre um objeto protobuf, então, em vez de codificar os nomes dos campos manualmente, podíamos fazer o seguinte:
void copyFields(GeneratedMessageV3 fromProto, TableRow toRow) { allFields = fromProto.getDescriptorForType().getFields(); for (Descriptors.FieldDescriptor field: allFields) { Object value = fields.get(field); String columnName = field.getName(); switch (field.getJavaType()) { case STRING: if (value != null) { toRow.set(columnName, value); } break;...
É só isso! Isso reduziu nosso código repetitivo e agora não precisamos nos preocupar em atualizar o código Java (observe que você ainda precisa reimplantar o job do dataflow para qualquer alteração de esquema, para que o executor do job saiba da definição mais recente do proto)
Disponibilizamos o código publicamente no repositório abaixo para que a comunidade não precise reinventar a roda — https://github.com/sardine-ai/proto-to-bq-java
Se você tiver algum feedback, entre em contato comigo https://twitter.com/kazukinishiura
Estamos contratando para todas as áreas de engenharia — https://www.sardine.ai/careers

