繁体   English   中英

尝试解析从 Google Cloud PubSub 检索到的协议缓冲区架构时出现“错误:非法令牌‘字符串’”

[英]"Error: Illegal token 'string'" when trying to parse protocol buffer schema retrieved from Google Cloud PubSub

如果您正在阅读本文,我希望您熟悉 Google Cloud PubSub、PubSub 主题和这些主题的架构。 :)。

当为主题定义模式是 GC pubsub 时,您有两种语法选择 - AVRO 和 Protocol Buffer。 我在使用 AVRO 方面取得了成功,但是在尝试使用 Protocol Buffer 时,我遇到了一个我不知道如何修复的错误。

这是 proto2 语法中的模式:

syntax = "proto2";

message ProtocolBuffer {
  string event_name = 1;
  string user_id = 2;
}

这与开始在 GC pubsub 中创建模式并选择 Protocol Buffer 时开箱即用的结果非常接近,我假设 GC pubsub 不喜欢 proto3 格式,因为它默认为 proto2。

我有一个基于 NodeJS 的云 Function,它在 GC Firestore 中创建文档时被调用。 我的目标是从 Firestore 获取数据并输入 BigQuery。

这是我的 Cloud Function 代码:

const Firestore = require('@google-cloud/firestore');
const { PubSub } = require('@google-cloud/pubsub');
const protobuf = require('protobufjs');

const firestore = new Firestore();
const pubsub = new PubSub();

exports.publishToBigQuery = async (event, context) => {
    console.log("event", JSON.stringify(event, 2, null));
    console.log("context", JSON.stringify(context, 2, null));
    const affectedDoc = firestore.doc(`messages/${context.params.documentId}`);

    try {
        const documentSnapshot = await affectedDoc.get();
        if (documentSnapshot.exists) {
            const firestoreData = documentSnapshot.data();

            const topic = pubsub.topic('firestore-document-created-with-proto-schema');

            const schema = pubsub.schema('event-pb-bq');
            const info = await schema.get();
            console.log('info', info);

            let root = new protobuf.Root();
            const type = protobuf.parse(info.definition);
            console.log('type', type);
            const ProtocolBuffer = type.root.lookupType('ProtocolBuffer');
            console.log('ProtocolBuffer', ProtocolBuffer);
            const message = ProtocolBuffer.create(firestoreData);
            console.log('message', message);
            const data = Buffer.from(message.toJSON());
            console.log('data', data);

            const value = await topic.publishMessage({data});
            console.log("Message published", value);
        } else {
            console.log("Document doesn't exist", JSON.stringify(affectedDoc));
        }
    } catch (error) {
        console.error("Error when fetching document", error);
    };
};

我在const type = protobuf.parse(info.definition);上收到此错误线。 我不知道后面的行是否正确。 他们是猜测。 如果无法解析模式源,那么我就卡住了。

这是错误堆栈跟踪:

event {"oldValue":{},"updateMask":{},"value":{"createTime":"2022-09-09T16:08:59.107887Z","fields":{"event_name":{"stringValue":"fridayeventname"},"user_id":{"stringValue":"fridayuserid"}},"name":"projects/myproject/databases/(default)/documents/messages/jH9W7SQj2aLh7eK8lRCl","updateTime":"2022-09-09T16:08:59.107887Z"}}
context {"eventId":"a00ecca0-0740-4cf8-94bf-15828af8e180-0","eventType":"providers/cloud.firestore/eventTypes/document.create","notSupported":{},"params":{"documentId":"jH9W7SQj2aLh7eK8lRCl"},"resource":"projects/myproject/databases/(default)/documents/messages/jH9W7SQj2aLh7eK8lRCl","timestamp":"2022-09-09T16:08:59.107887Z"}
info {
 name: 'projects/myproject/schemas/event-pb-bq',
 type: 'PROTOCOL_BUFFER',
 definition: 'syntax = "proto2";\n' +
 '\n' +
 'message ProtocolBuffer {\n' +
 ' string event_name = 1;\n' +
 ' string user_id = 2;\n' +
 '}\n'
}
Error when fetching document Error: illegal token 'string' (line 4)
 at illegal (/workspace/node_modules/protobufjs/src/parse.js:96:16)
 at parseType_block (/workspace/node_modules/protobufjs/src/parse.js:347:31)
 at ifBlock (/workspace/node_modules/protobufjs/src/parse.js:290:17)
 at parseType (/workspace/node_modules/protobufjs/src/parse.js:308:9)
 at parseCommon (/workspace/node_modules/protobufjs/src/parse.js:261:17)
 at Object.parse (/workspace/node_modules/protobufjs/src/parse.js:829:21)
 at exports.publishToBigQuery (/workspace/index.js:26:35)

我在任何地方都找不到可以从 PubSub 检索模式源然后使用它来格式化 pubsub 消息的示例。 有人有想法么?

谢谢。

问题是 Pub/Sub 的模式验证过于宽松。 在这种情况下,提供的模式定义被认为是无效的,因为它是 proto2 并且没有为字段指定可选、重复或必需的。 Node 的 protobuf 解析器捕捉到了这一事实,而 Pub/Sub 的验证器隐含地将这些视为可选。

如果将架构更改为以下内容,它应该可以工作:

 syntax = "proto2";

 message ProtocolBuffer {
   optional string event_name = 1;
   optional string user_id = 2;
 }

对于在这种情况下对验证器的改进的跟进,您可以看到为它输入的问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM