You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Google Cloud PubSub获取Protocol Buffer Schema解析报错求助

问题:PubSub Schema解析时出现"illegal token 'string'"错误

我熟悉Google Cloud PubSub、Topic及对应Schema,在为GC PubSub的Topic定义Protocol Buffer类型Schema(采用proto2语法)后,通过Node.js编写的Cloud Function从Firestore读取数据,尝试发布到关联该Schema的PubSub Topic。但调用protobuf.parse解析从PubSub获取的Schema定义时,出现“illegal token 'string'”错误。以下是相关信息及解决思路:

相关代码与信息

Schema内容

syntax = "proto2";

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

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);
    };
};

错误栈

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)

解决思路

1. 修复Schema定义中的语法错误

从日志输出的info.definition可以看到,第一行syntax = "proto2";;多了一个分号,这是导致protobufjs解析失败的直接原因:

  • 重新在PubSub中更新Schema,将第一行修正为syntax = "proto2";
  • 若无法直接修改已创建的Schema,需删除现有Schema后重新创建。

2. 修正Firestore数据处理逻辑

从event日志可见,Firestore返回的数据是嵌套结构(如event_name对应{stringValue: "fridayeventname"}),直接用documentSnapshot.data()获取的数据不符合protobuf期望的扁平结构,需先转换:

// 转换Firestore数据为扁平结构
const firestoreData = documentSnapshot.data();
const formattedData = {};
for (const key in firestoreData) {
  if (firestoreData[key].stringValue) {
    formattedData[key] = firestoreData[key].stringValue;
  }
  // 可根据实际字段类型扩展其他处理,比如numberValue等
}

3. 修正消息发布的编码方式

当前代码用Buffer.from(message.toJSON())是错误的,protobuf消息需编码为二进制格式才能正确发布到PubSub:

// 替换原有的data生成逻辑
const message = ProtocolBuffer.create(formattedData);
// 验证消息格式是否符合Schema
const errMsg = ProtocolBuffer.verify(message);
if (errMsg) throw new Error(errMsg);
// 编码为二进制Buffer
const data = ProtocolBuffer.encode(message).finish();

4. 可选:预加载本地Schema文件

若不想每次从PubSub拉取Schema解析,可直接在代码中引入本地proto文件,避免因PubSub返回的Schema格式异常导致问题:

const root = await protobuf.load('path/to/your/schema.proto');
const ProtocolBuffer = root.lookupType('ProtocolBuffer');

内容的提问来源于stack exchange,提问作者T D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:40:48