Облачная функция Google в Javascript завершается до завершения функции - PullRequest
0 голосов
/ 05 ноября 2019

Чтобы объяснить мой вариант использования, у меня есть вычислительный движок GCP, на котором запущено собственное приложение с поддержкой RESTful API. Я хочу прочитать API RESTful, чтобы проверить, есть ли какие-либо обновления записей в приложении.

Если есть новые записи, я хочу добавить их в таблицу BigQUery, которая используется для построенияотчет в Data Studio.

У меня проблема в том, что функция завершается до завершения вставки в BigQuery. Я добавил async, подождите, пока я не получу правильную формулу для этой работы для меня, поэтому я обращаюсь к сообществу за информацией. Я ценю любой совет, который я могу получить по этому вопросу. Вот мой код `'use strict';

 // Request Data From A URL
 var axios = require('axios');
 var https = require('https');

  // Var Firebase Functions
 var functions = require('firebase-functions');
 const admin = require('firebase-admin');

 // Initalise App
 admin.initializeApp;

// Setting Timeout in Seconds - default is 1 second
// The maximum value for timeoutSeconds is 540, or 9 minutes. Valid values for memory are:
// 128MB, 256MB, 512MB, 1GB, 2GB

const runtimeOpts = {
  timeoutSeconds: 300,
  memory: '512MB'
}

exports.getEmilyNoonreporttoBigQuery = functions
  .runWith(runtimeOpts)
  .region('europe-west1')
  .https.onRequest(async(req, res) => {
   try {
   // Imports the Google Cloud client library
   const {BigQuery} = require('@google-cloud/bigquery');

  // Create a client
  const bigquery = new BigQuery();

  //Make use of a dataset
  const dataset = bigquery.dataset('noonreport');

//Make use of a table
const table = dataset.table('noonreport');

// The API Key
  let apikey = 'API-KEY';

  // Table to get data from
  var apitable = 'noon_report';

  // From were the data comes
  var shipid = '1';

  // Get the current date 
  var today = new Date();
  var dd = String(today.getDate()).padStart(2, '0');
  var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
  var yyyy = today.getFullYear();

  today = yyyy + '-' + mm + '-' + dd;

  var url = 'https://emily.apps.gl3/api/' + shipid + '/' + apitable + '?apikey=' + apikey + '&syncdate=' + today;
  console.log('today', today);
  console.log('url', url);

  // At request level
  const agent = new https.Agent({  
    rejectUnauthorized: false
  });

//  axios.get(url)
axios.get(url, { httpsAgent: agent })
    .then(resp => {
      try {
      console.log("Response " + resp);
      for(let artno in resp.data.noon_report) {
        // Create the BigQuery Row
          var row = {
            ship: resp.data.noon_report[artno].noon_report.ship,
            local_time: resp.data.noon_report[artno].noon_report.local_time || resp.data.noon_report[artno].noon_report.report_date,
            status: resp.data.noon_report[artno].noon_report.status,
            location: resp.data.noon_report[artno].noon_report.location,
            course: resp.data.noon_report[artno].noon_report.course,
            next_port: resp.data.noon_report[artno].noon_report.next_port,
            ETD: resp.data.noon_report[artno].noon_report.ETD,
            ETA: resp.data.noon_report[artno].noon_report.ETA,
            distance_made: resp.data.noon_report[artno].noon_report.distance_made,
            stoppage: resp.data.noon_report[artno].noon_report.stoppage,
            avg_speed: resp.data.noon_report[artno].noon_report.avg_speed,  
            mgo_rob: resp.data.noon_report[artno].noon_report.mgo_rob,
            mgo_consumed: resp.data.noon_report[artno].noon_report.mgo_consumed,
            mgo_received: resp.data.noon_report[artno].noon_report.mgo_received,
            fw_rob: resp.data.noon_report[artno].noon_report.fw_rob,
            fw_consumed: resp.data.noon_report[artno].noon_report.fw_consumed,
            fw_produced: resp.data.noon_report[artno].noon_report.fw_produced,
            fw_received: resp.data.noon_report[artno].noon_report.fw_received,
            underway_hours: resp.data.noon_report[artno].noon_report.underway_hours,
            me_rh: resp.data.noon_report[artno].noon_report.me_rh,
            heli_flight_hours: resp.data.noon_report[artno].noon_report.heli_flight_hours,
            heli_fuel_consumed: resp.data.noon_report[artno].noon_report.heli_fuel_consumed,
            heli_fuel_rob: resp.data.noon_report[artno].noon_report.heli_fuel_rob,
            name_of_pilot: resp.data.noon_report[artno].noon_report.name_of_pilot,
            nature_of_flight: resp.data.noon_report[artno].noon_report.nature_of_flight,
            wind_direction: resp.data.noon_report[artno].noon_report.wind_direction,
            wind_force: resp.data.noon_report[artno].noon_report.wind_force,
            sea_state: resp.data.noon_report[artno].noon_report.sea_state,
            weather: resp.data.noon_report[artno].noon_report.weather,
            visibility: resp.data.noon_report[artno].noon_report.visibility,
            barometer: resp.data.noon_report[artno].noon_report.barometer,
            air_temp: resp.data.noon_report[artno].noon_report.air_temp,
            remarks: resp.data.noon_report[artno].noon_report.remarks,
            cur_timestamp: resp.data.noon_report[artno].noon_report.cur_timestamp,
            cancelled: resp.data.noon_report[artno].noon_report.cancelled,
            arrivaldep: resp.data.noon_report[artno].noon_report.arrivaldep,
            shorepw: resp.data.noon_report[artno].noon_report.shorepw,  
            lo_rob: resp.data.noon_report[artno].noon_report.lo_rob,
            lo_consumed: resp.data.noon_report[artno].noon_report.lo_consumed,
            petrol_rob: resp.data.noon_report[artno].noon_report.petrol_rob,
            petrol_consumed: resp.data.noon_report[artno].noon_report.petrol_consumed,
            heli_fuel_received: resp.data.noon_report[artno].noon_report.heli_fuel_received,
            petrol_received: resp.data.noon_report[artno].noon_report.petrol_received,
            lo_received: resp.data.noon_report[artno].noon_report.lo_received,
            campaign: resp.data.noon_report[artno].noon_report.campaign,
            projectLeader: resp.data.noon_report[artno].noon_report.projectLeader,
            visitorsOpen: resp.data.noon_report[artno].noon_report.visitorsOpen,
            fundsOpen: resp.data.noon_report[artno].noon_report.fundsOpen,
            vipsOpen: resp.data.noon_report[artno].noon_report.vipsOpen,
            pressOpen: resp.data.noon_report[artno].noon_report.pressOpen,
            volsOpen: resp.data.noon_report[artno].noon_report.volsOpen,
            officeOpen: resp.data.noon_report[artno].noon_report.officeOpen,
            clockChange: resp.data.noon_report[artno].noon_report.clockChange,
            operPrepared: resp.data.noon_report[artno].noon_report.operPrepared,
            techPrepared: resp.data.noon_report[artno].noon_report.techPrepared,
            port_of_call: resp.data.noon_report[artno].noon_report.port_of_call|| "No Author Defined",
            time_zone: resp.data.noon_report[artno].noon_report.time_zone,
            report_date: resp.data.noon_report[artno].noon_report.report_date,
            report_by: resp.data.noon_report[artno].noon_report.report_by,
            berth_anchor_hours: resp.data.noon_report[artno].noon_report.berth_anchor_hours,
            ship_activity: resp.data.noon_report[artno].noon_report.ship_activity,
            uuid: resp.data.noon_report[artno].noon_report.uuid,
            is_submit: resp.data.noon_report[artno].noon_report.is_submit,
            helicopter_used: resp.data.noon_report[artno].noon_report.helicopter_used,
            position_lat: resp.data.noon_report[artno].noon_report.position_lat,
            position_lon: resp.data.noon_report[artno].noon_report.position_lon,
            me1_distance: resp.data.noon_report[artno].noon_report.me1_distance,
            me1_uw_hours: resp.data.noon_report[artno].noon_report.me1_uw_hours,
            me2_distance: resp.data.noon_report[artno].noon_report.me2_distance,
            me2_uw_hours: resp.data.noon_report[artno].noon_report.me2_uw_hours,
            me1_2_distance: resp.data.noon_report[artno].noon_report.me1_2_distance,
            me1_2_uw_hours: resp.data.noon_report[artno].noon_report.me1_2_uw_hours,
            edrive_distance: resp.data.noon_report[artno].noon_report.edrive_distance,
            edrive_uw_hours: resp.data.noon_report[artno].noon_report.edrive_uw_hours,
            sail_distance: resp.data.noon_report[artno].noon_report.sail_distance,
            sail_uw_hours: resp.data.noon_report[artno].noon_report.sail_uw_hours,
            e_motorsail_distance: resp.data.noon_report[artno].noon_report.e_motorsail_distance,
            e_motorsail_uw_hours: resp.data.noon_report[artno].noon_report.e_motorsail_uw_hours,
            me_motorsail_distance: resp.data.noon_report[artno].noon_report.me_motorsail_distance,
            me_motorsail_uw_hours: resp.data.noon_report[artno].noon_report.me_motorsail_uw_hours,
            motoring_edrive_distance: resp.data.noon_report[artno].noon_report.motoring_edrive_distance,
            motoring_edrive_uw_hours: resp.data.noon_report[artno].noon_report.motoring_edrive_uw_hours,
            drifting_hours: resp.data.noon_report[artno].noon_report.drifting_hours,
            country: resp.data.noon_report[artno].noon_report.author          
          };
          console.log("ROW TO INSERT " + JSON.stringify(row));
          insertBigQuery(row, table);
        }
        console.log("For Loop end");
        res.status(200).send("OK");
      }
      catch (error) {
        // Handle the error
        console.log(error);
        response.status(500).send(error);
      }
    })
  }
  catch (error) {
      // Handle the error
      console.log(error);
      response.status(500).send(error);
    }

    //This Query inserts data after charges completed
    async function insertBigQuery(row, table){
     return await table.insert(row, function(err, apiResponse) {
        //console.log('Insert', apiResponse);
        if (!err) {
         console.log("[BIGQUERY] - Saved.");
        } else {
        console.error(`error table.insert: ${JSON.stringify(err)}`)
         // To finish http function return value
        }
      });
    }
});

`

У меня есть цикл for для распаковки данных API REStFul и построения строки для вставки в BigQuery. Я использую планировщик Cloud для запуска этой функции с помощью триггера HTTP.

URL-адрес, который я использую, предназначен для внутреннего приложения, поэтому он недоступен снаружи. Я получаю данные и распаковываю данные, функция завершается до того, как данные были вставлены в BigQuery.

Я попытался добавить ожидание в строку, где я вызываю функцию вставки BigQuery, которая не сработала.

await insertBigQuery(row, table);

Не получилось, в поисках помощи.

1 Ответ

1 голос
/ 05 ноября 2019

Мне кажется, я вижу пару вопросов. Если мы посмотрим на API для табличных объектов BigQuery с именем insert, то увидим, что он возвращает Promise. Отлично. Мы также видим, что он имеет дополнительную функцию обратного вызова. Я не уверен, что вы должны использовать оба. Вы либо говорите, что результат будет известен как обещание, которое впоследствии будет решено, либо говорите, что результат будет сообщен вам с помощью обратного вызова. Я не уверен, что оба будут удовлетворены. Я бы посоветовал просто использовать Обещания.

Однако, я думаю, что большая проблема заключается в этой логике:

async function insertBigQuery(row, table){
  return await table.insert(row, function(err, apiResponse) {
    //console.log('Insert', apiResponse);
    if (!err) {
      console.log("[BIGQUERY] - Saved.");
     } else {
       console.error(`error table.insert: ${JSON.stringify(err)}`)
       // To finish http function return value
     }
  });
}

Нетто .... у вас есть:

async function funcName() {
   return await asyncFuncCall();
}

Я думаю, что это может быть вашей проблемой. Приставляя вашу функцию (funcName) к async, вы заявляете, что функция вернет Promise и что вызывающая сторона НЕ будет блокировать ожидание возврата, но вызывающая сторона сама получит обещание.

У меня есть подлое подозрение, что вы действительно хотите иметь:

async function funcName() {
   return asyncFuncCall();
}

, а затем, когда вы вызываете funcName (), вам нужно:

let finalResult = await funcName();

или

funcName().then((finalResult) => { ... logic ... });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...