使用 Batch 对象时云函数停止执行

Posted

技术标签:

【中文标题】使用 Batch 对象时云函数停止执行【英文标题】:Cloud function stop executing when Batch object is being used 【发布时间】:2019-01-19 20:45:01 【问题描述】:

我正在使用 Google Cloud Function 对 bigQuery 执行查询,并在 firestore 时存储结果。

我的问题是,一旦我尝试使用 firestore 批处理对象,云功能就会停止执行。

使用二分法,我认为当我包含批处理对象代码时,函数突然停止工作。

我尝试将函数的内存增加到 1GB,但没有运气。 (目前使用的是 128mb)

const BigQuery  = require('@google-cloud/bigquery');
const Firestore = require('@google-cloud/firestore');

const bigquery   = new BigQuery  ();
const firestore  = new Firestore ();

const fsCollectionName = 'ul_queteur_stats_per_year';


const queryStr = "the bigquery query";


function handleError(err)
  //skipped


/**
 * Triggered from a message on a Cloud Pub/Sub topic.
 *
 * @param !Object event Event payload.
 * @param !Object context Metadata for the event.
 */
exports.ULQueteurStatsPerYear = (event, context) => 
  const pubsubMessage = event.data;
  const parsedObject  = JSON.parse(Buffer.from(pubsubMessage, 'base64').toString());

  console.log("Recieved Message : "+JSON.stringify(parsedObject));
  // ul_id:parsedObject.ul_id 

  const queryObj = 
    query: queryStr,
    params: 
      ul_id: parsedObject.ul_id
    
  ;

  bigquery
    .query(queryObj)
    .then((data) => 
      console.log("Query Successful, # rows : "+data.length+" data[0].length:"+data[0].length);
      //rows : ["amount":367.63,"weight":2399.3,"time_spent_in_minutes":420]
      const rows = data[0];
      console.log("Query Successful");

      const batch       = firestore.batch();

      console.log("Batch Created ");

      console.log("Getting Collection");
      const collection  = firestore.collection(fsCollectionName);
      console.log("Getting Collection '"+fsCollectionName+"' retrieved");
      //#####################################
      for(let i=0;i<rows.length;i++)
      
        console.log("getting a new DocId");

        const docRef = collection.doc();

        console.log("Adding to docRef='"+docRef.id+"' : "+JSON.stringify(rows[i]));
        batch.set(docRef, rows[i]);
        console.log("Added to batch");
      


      console.log("Commiting batch insert");
      batch.commit().then(() => 
        console.log('Successfully executed batch');
      );
      //#####################################

    )
    .catch(err => 
      handleError(err);
    );

;

预期:

在 Firestore 中插入的数据

实际结果:

如果我删除 //####################################

然后我在 stackdriver 中获取每个日志。 (第一个说有 420 行)

如果我让代码之间 //##################################### (或者只是 batch.commit() 部分,或者只是 for 循环部分)

我只得到第一个日志,然后什么也没有。

查询成功,# rows : 1 data[0].length:420

即使我将整个代码放在带有异常的 console.log 的 try/catch 块中,我在堆栈驱动程序中也看不到错误。

解决方案

解决方案是返回 bigquery 承诺。

所以上面的代码应该改成:

return bigquery
.query(queryObj)
.then(...);

感谢Doug 的帮助!

【问题讨论】:

尝试return batch.commit(),然后在最外层添加另一个then 【参考方案1】:

您需要返回一个在所有异步工作完成后解决的 Promise。现在,您没有返回任何内容,这意味着该函数将在您的查询完成之前几乎立即终止并关闭。

您需要注意代码使用的所有承诺,包括查询和所有批量提交。您不能忽略任何 API 返回的任何承诺,否则工作将在完成之前终止。

【讨论】:

这仍然不起作用。我认为我应该返回 BigQuery 对象,因为它至少需要 3 秒才能执行。 "返回 bigquery.query(queryObj).then(...);"确实有效!感谢您的帮助!

以上是关于使用 Batch 对象时云函数停止执行的主要内容,如果未能解决你的问题,请参考以下文章

网时网时云服务器存放数据是否安全

网时云:香港服务器被cc攻击了怎么办?

BATCH - 无法从函数的变量中返回正确的值

停止执行 jQuery 函数

Python面向对象(11)生成器

Spring Boot and Batch:根据 application.properties 值停止批处理