Pubsub to bigquery subscription with AVRO schema ignores messages with value for last column

Viewed 28

I have a pubsub topic with an avro schema, a bigquery subscription and a matching bigquery table. To test this I use a python script to publish a number of records.

Published records that have None or no value for the last column appear in bigquery soon after publishing. As soon as a value is specified for the last column, the record does not appear. I changed the column order and it is always the last column, that generates the issue.

How can I fix that?

Avro schema

{
  "type": "record",
  "name": "incoming_telemetry",
  "doc": "Telemetry message from herby device",
  "fields": [
    {"name": "deviceId", "type": "string"},
    {"name": "timestamp", "type": "string"},
    {"name": "waterTableRange", "type": ["null", "float"]},
    {"name": "batteryCapacity", "type": ["null", "float"]},
    {"name": "batteryCurrent", "type": ["null", "float"]},
    {"name": "solarVoltage", "type": ["null", "float"]},
    {"name": "batteryVoltage", "type": ["null", "float"]},
    {"name": "temperature", "type": ["null", "float"]},
    {"name": "wifiStrength", "type": ["null", "float"]},
    {"name": "flowRate", "type": ["null", "float"]}
  ]
}

Bigquery schema

[
  {
    "name": "timestamp",
    "type": "TIMESTAMP",
    "mode": "REQUIRED"
  },
  {
    "name": "deviceId",
    "type": "STRING",
    "mode": "REQUIRED"
  },
  {
    "name": "waterTableRange",
    "type": "FLOAT",
    "mode": "NULLABLE"
  },
  {
    "name": "batteryCapacity",
    "type": "FLOAT",
    "mode": "NULLABLE"
  },
  {
    "name": "batteryCurrent",
    "type": "FLOAT",
    "mode": "NULLABLE"
  },
  {
    "name": "solarVoltage",
    "type": "FLOAT",
    "mode": "NULLABLE"
  },
  {
    "name": "batteryVoltage",
    "type": "FLOAT",
    "mode": "NULLABLE"
  },
  {
    "name": "temperature",
    "type": "FLOAT",
    "mode": "NULLABLE"
  },
  {
    "name": "wifiStrength",
    "type": "FLOAT",
    "mode": "NULLABLE"
  },
  {
    "name": "flowRate",
    "type": "FLOAT",
    "mode": "NULLABLE"
  }
]

python script

import io
from datetime import datetime, timezone

import avro.schema
import google.auth
from avro.io import DatumWriter, BinaryEncoder, BinaryDecoder, DatumReader
from google.cloud import pubsub_v1, bigquery

INCOMING_TOPIC_ID = 'incoming-telemetry-v1.0'
SCHEMA_FILE = '../../schemas/incoming_telemetry_v1.0.avsc'

DATASET_ID = 'telemetry'
TABLE_ID = 'raw-telemetry'

GCP_TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'

timestamp = datetime.now(timezone.utc).strftime(GCP_TIMESTAMP_FORMAT)

records = [
    {
        'deviceId': '1',
        'timestamp': timestamp,
        'waterTableRange': None,
        'batteryCapacity': None,
        'batteryCurrent': None,
        'solarVoltage': None,
        'batteryVoltage': None,
        'temperature': None,
        'wifiStrength': None,
        'flowRate': None,
    },
    {
        'deviceId': '2',
        'timestamp': timestamp,
    },
    {
        'deviceId': '3',
        'timestamp': timestamp,
        'waterTableRange': 1.1,
        'batteryCapacity': 2.2,
        'batteryCurrent': 3.3,
        'solarVoltage': 4.4,
        'batteryVoltage': 5.5,
        'temperature': 6.6,
        'wifiStrength': 7.7,
        'flowRate': None,
    },
    {
        'deviceId': '4',
        'timestamp': timestamp,
        'wifiStrength': 7.7,
    },
    {
        'deviceId': '5',
        'timestamp': timestamp,
        'waterTableRange': 1.1,
        'batteryCapacity': 2.2,
        'batteryCurrent': 3.3,
        'solarVoltage': 4.4,
        'batteryVoltage': 5.5,
        'temperature': 6.6,
        'wifiStrength': 7.7,
        'flowRate': 8.8,
    },

    {
        'deviceId': '6',
        'timestamp': timestamp,
        'flowRate': 8.8,
    },
]

project_id = google.auth.default()[1]
publisher_client = pubsub_v1.PublisherClient()
topic_path = publisher_client.topic_path(project_id, INCOMING_TOPIC_ID)

file = open(SCHEMA_FILE, 'rb')
schema = avro.schema.parse(file.read())
writer = DatumWriter(schema)


for record in records:
    byte_stream = io.BytesIO()
    encoder = BinaryEncoder(byte_stream)
    writer.write(record, encoder)
    data = byte_stream.getvalue()
    byte_stream.flush()
    future = publisher_client.publish(topic_path, data)
    print(f"Published message ID: {future.result()}")

records 1-4 appear while records 5 + 6 are nowhere.

results in bigquery enter image description here

0 Answers
Related