En Sardine usamos protocol buffers (protobuf) en todas partes. Es un formato de serialización ligero, neutral en cuanto al lenguaje y con tipado.
Usamos protobuf para definir el esquema de datos de las tablas de BigQuery y también para generar el código del servidor backend (en go) a partir del mismo archivo protobuf. Nuestros servidores backend completan el struct de golang (generado a partir de protobuf), lo envían a pubsub y, luego, los jobs de dataflow los recogen en BigQuery.

Este patrón simple funcionó bastante bien, con una salvedad. Cuando empezamos, no había una solución clara sobre cómo convertir un objeto de pubsub en una inserción de fila de BigQuery, así que necesitábamos escribir código repetitivo como el siguiente para copiar datos de un objeto a otro:
TableRow clientMetadataRow = new TableRow() .set("session_key", clientMetadata.getSessionKey()) .set("client_id", clientMetadata.getClientId()) .set("revision", clientMetadata.getRevision()) .set("user_id", clientMetadata.getUserId())...
Esto era muy tedioso y propenso a errores. Cuando añadíamos un nuevo campo en la tabla de BigQuery, también teníamos que actualizar el código repetitivo anterior. Debía existir una mejor solución para esto.
(nota al margen: si hoy inicias un nuevo servicio, podrías usar JSON en lugar de protobuf como formato de serialización para pubsub, y luego usar la plantilla oficial de trabajo pubsub-to-bigquery de Google (beta) —https://cloud.google.com/dataflow/docs/guides/templates/provided-streaming)
Resulta que se puede iterar dinámicamente sobre un objeto protobuf, así que en lugar de codificar los nombres de los campos manualmente, podíamos hacer esto:
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;...
¡Y eso es todo! Redujo nuestro código repetitivo y ahora no tenemos que preocuparnos por actualizar el código Java (ten en cuenta que aún debes volver a desplegar el job de dataflow ante cualquier cambio de esquema, para que el ejecutor del job conozca la última definición del proto)
Hicimos público el código en el siguiente repositorio para que la comunidad no tenga que reinventar la rueda — https://github.com/sardine-ai/proto-to-bq-java
Si tienes algún comentario, no dudes en contactarme https://twitter.com/kazukinishiura
Estamos contratando para todos los roles de ingeniería — https://www.sardine.ai/careers

