简体   繁体   English

GCP Nodejs8 Cloud Function - 同步 PubSub 发布

[英]GCP Nodejs8 Cloud Function - Synchronous PubSub publish

I'm struggling with a javascript/Nodejs8 Google Cloud Function to publish payloads to Google PubSub.我正在努力使用 javascript/Nodejs8 Google Cloud Function 将有效负载发布到 Google PubSub。

So I have a Cloud Function triggered by HTTP requests and the request body is then published to a pubsub topic (configured for pull mode).所以我有一个由 HTTP 请求触发的云 Function,然后请求正文被发布到一个 pubsub 主题(配置为拉模式)。

Here is my code:这是我的代码:

const {PubSub} = require('@google-cloud/pubsub');
const pubsub = new PubSub();
const topic = pubsub.topic('my-fancy-topic');

function formatPubSubMessage(reqObj){
    // the body is pure text
    return Buffer.from(reqObj.body);
};

exports.entryPoint = function validate(req, res) {

topic.publish(formatPubSubMessage(req)).then((messageId) => {
            console.log("sent pubsub message with id :: " + messageId)
        });

res.status(200).json({"res":"OK"});
};

My issue is that the cloud function finishes executing before the pubsub message being published (in logs, the log "Function execution took X ms, finished with status code: 200" shows up around 30 or 40 seconds before the my pubsub log. I also had several times a log with "Ignoring exception from a finished function" and I dont get my pubsub log)我的问题是云 function 在发布 pubsub 消息之前完成执行(在日志中,日志“函数执行需要 X 毫秒,以状态代码完成:200”在我的 pubsub 日志之前大约 30 或 40 秒出现。我也有几次日志“忽略已完成功能的异常”,但我没有得到我的 pubsub 日志)

I'm not a javascript or nodejs specialist and I don't master javascript promises neither but I was wondering if I could make the publish synchronous.我不是 javascript 或 nodejs 专家,我也不掌握 javascript 的承诺,但我想知道是否可以使发布同步。 I'm thinking as well that I might be doing something wrong here !我也在想我可能在这里做错了什么!

Thank you in advance for your help.预先感谢您的帮助。

Right now, this code is sending a response before the publish is complete.现在,此代码在发布完成之前发送响应。 When the response is sent, the function is terminated, and ongoing async work might not complete.发送响应后,function 将终止,正在进行的异步工作可能无法完成。

What you should do instead is send the response only after the publish is complete, which means putting that line of code in the then callback.相反,您应该做的是仅在发布完成后发送响应,这意味着将该行代码放在then回调中。

exports.entryPoint = function validate(req, res) {

    topic.publish(formatPubSubMessage(req)).then((messageId) => {
        console.log("sent pubsub message with id :: " + messageId)
        res.status(200).json({"res":"OK"});
    });

};

I suggest spending some time learning about how promises work, as this is crucial to building functions that work correctly.我建议花一些时间了解 Promise 是如何工作的,因为这对于构建正确工作的函数至关重要。

In your logic, your callback / event handler function is being called when the HTTP message arrives.在您的逻辑中,当 HTTP 消息到达时,正在调用您的回调/事件处理程序 function。 You then execute a publish() function.然后执行 publish() function。 Executing a publish is an asynchronous activity.执行发布是一个异步活动。 This means that it make take some time for the publish to complete and since JavaScript (intrinsically) doesn't want to block, it returns immediately with a promise that you can then use to be notified when the asynchronous work has completed.这意味着发布需要一些时间才能完成,并且由于 JavaScript(本质上)不想阻止,它会立即返回 promise,然后您可以使用它在异步工作完成时收到通知。 Immediately after executing the publish() your logic executes a res.status(....) which sends a response to the HTTP request and that is indeed the end of the flow request from the HTTP client.在执行 publish() 之后,您的逻辑立即执行 res.status(....) ,它发送对 HTTP 请求的响应,这确实是来自 HTTP 客户端的流请求的结束。 The asynchronous publish is still cooking and when it itself completes, then the callback for the publish occurs and you log a response.异步发布仍在进行中,当它本身完成时,会发生发布回调并记录响应。

Unfortunately, this is not a good practice as documented by Google here...不幸的是,这不是谷歌在这里记录的好习惯......

https://cloud.google.com/functions/docs/bestpractices/tips#do_not_start_background_activities https://cloud.google.com/functions/docs/bestpractices/tips#do_not_start_background_activities

In this last story, the function you call validate will still end prior to the publish being completed.在最后一个故事中,您调用validate的 function 仍将在发布完成之前结束。 If you want to block while the publish() executes (effectively making it synchronous), you can use the JavaScript await key word.如果您想在 publish() 执行时阻塞(有效地使其同步),您可以使用 JavaScript await关键字。 Loosely, something like:松散地,像:

try {
   let messageId = await topic.publish(....);
   console.log(...);
catch(e) {
 ...
}

You will also need to flag the functions as being async .您还需要将函数标记为async For example:例如:

exports.entryPoint = async function validate(req, res) {
   ...

See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function请参阅: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

You can also simply return a Promise from the function and the callback function will not be considered resolved until the Promise as a whole is resolved. You can also simply return a Promise from the function and the callback function will not be considered resolved until the Promise as a whole is resolved.

The bottom line is to study Promises in depth.底线是深入研究 Promise。

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

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