【问题标题】:Bigquery Load in Cloud Function in Node JS getting Job ID without waiting节点JS中云函数中的Bigquery加载无需等待即可获取作业ID
【发布时间】:2019-07-23 20:33:08
【问题描述】:

我正在努力从下面的云函数代码中获取 BigQuery 作业 ID。 我需要工作 ID 以验证工作是否成功完成

这是我的代码:

 var storage = new Storage({projectId: process.env.PROJECT_ID});
    var tableId = getTableID(file);

    const metadata = {
        sourceFormat: 'CSV',
        skipLeadingRows: 1,
        autodetect: false,
        writeDisposition: 'WRITE_APPEND',
        fieldDelimiter: process.env.DELIMITER,
        allowJaggedRows: 'TRUE'
    };

    console.log(`The file ${file.name} has been successfully picked up and going to be stored in table ${process.env.PROJECT_ID}:${process.env.DATASET_ID}.${tableId}.`);
    outboundHandler.sendStatusUpdate(file.name, process.env.IN_PROGRESS_CODE);
    var errorsState = false;

// Loads data from a Google Cloud Storage file into the table
   const [job] =   bigquery
        .dataset(process.env.DATASET_ID)
        .table(tableId)
        .load(storage.bucket(file.bucket).file(file.name), metadata);

          console.log(job.id);

【问题讨论】:

  • 您是否尝试过 JSON.stringify(job) 来查看来自调用的完整结构?也不清楚您使用的是哪个 bq 库
  • job 当前是一个 Promise。我使用 require('@google-cloud/bigquery');

标签: node.js google-bigquery google-cloud-functions


【解决方案1】:

我想避免使用 promise,因为我不想等到 Big Query Job 完成:

您可以在元数据对象中设置自己的 jopId 来监控 Job 状态并避免等待 Promise 响应。

来自 BigQuery 加载类文档

  • @param {string} [metadata.jobId] 基础作业的自定义 ID。
  • @param {string} [metadata.jobPrefix] 应用于基础作业 ID 的前缀。

这是一个 link 到 c# 中的示例,说明如何执行此操作

但是,根据您的描述,您的流程中似乎缺少一个错误。 我建议您尽可能使用Async/Await 而不是promise 来简化您的代码并帮助排除故障

// Imports the Google Cloud client library
const {BigQuery} = require('@google-cloud/bigquery');

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = "your-project-id";
// const filename = "/path/to/file.csv";
// const datasetId = "my_dataset";
// const tableId = "my_table";

// Creates a client
const bigquery = new BigQuery({projectId});

// Loads data from a local file into the table
const [job] = await bigquery
  .dataset(datasetId)
  .table(tableId)
  .load(filename);

console.log(`Job ${job.id} completed.`);

// Check the job's status for errors
const errors = job.status.errors;
if (errors && errors.length > 0) {
  throw errors;
}

【讨论】:

  • @Tmair Klein,谢谢,我添加了自定义作业 ID,并在 CF 外部(在 App 引擎服务中)验证大查询作业状态。至于使用 await 我有限制,因为我使用的是 NodeJS 6(Node JS 8 仍处于测试阶段)。谢谢!
【解决方案2】:

你需要进一步使用 Promise

const [job] =   bigquery
        .dataset(process.env.DATASET_ID)
        .table(tableId)
        .load(storage.bucket(file.bucket).file(file.name), metadata)
        .then(results => {
                const job = results[0];

                // load() waits for the job to finish
                console.log(`Job ${job.id} completed.`);

                // Check the job's status for errors
                const errors = job.status.errors;
                if (errors && errors.length > 0) {
                    //console.log(errors);
                    callback(errors);
                    //throw errors;
                } else {
                    callback();
                }
            })
            .catch(err => {
                //console.error('ERROR:', err);
                callback(err);
            });

确保在每次可能完成时都致电您的callback

我们的函数定义为exports.loadFileFromGCStoBigQuery = (data, callback) => {

【讨论】:

  • 谢谢奔腾,这正是我之前实现的方式。然而,对于我每天加载的 36 个文件,我只得到 75% 的响应,而 25% 的响应没有从 BigQuery 通知 JOB 的状态是什么。在另一个世界中,BigQuery 并没有放弃对 Promise 的响应
  • 请在附加评论中查看我的回复。
  • 尝试将第二个参数 callback 逻辑添加到您的函数中以进一步传递错误/成功,我们没有设置任何其他内容,当出现故障时我们会收到警报,我们会在 2 分钟内运行1000 个工作,一切正常。
  • 感谢您的回答,唯一的事情是我想绕过异步机制 (callback,Promise) 。我想立即获取 JOB ID
  • 您的文件有多大,每次运行有多少文件?我们有一个类似的代码开始显示 GCP 端的一些性能问题。我们有大约 36 个文件,每个文件大约 1.5 GB
猜你喜欢
  • 2020-04-18
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
  • 2021-09-27
  • 2016-09-24
  • 2020-11-06
  • 1970-01-01
  • 2014-05-18
相关资源
最近更新 更多