Медленные, ненадежные облачные функции Firebase - PullRequest
0 голосов
/ 26 апреля 2018

В создаваемом приложении пользователи могут запросить слово, и приложение обращается к онлайн-интерфейсу Оксфордского словаря API, чтобы получить определение, произношение и т. Д. Я использую облачные функции Firebase для HTTP-запроса и написанияответ на Cloud Firestore.Иногда это работает ... медленно.В девяти случаях из десяти данные не записываются в Firestore.

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const request = require('request'); // node module to send HTTP requests

admin.initializeApp();

exports.oxford_English_US = functions.firestore.document('Users/{userID}/English_American/Word_Request').onUpdate((change, context) => {
console.log(change.before.data());
console.log(change.after.data());
console.log(context.params.userID);
if (change.after.data().word != undefined) {
  let options = {
    url: 'https://od-api.oxforddictionaries.com/api/v1/entries/en/' + change.after.data().word + '/pronunciations%3Bregions%3Dus',
    headers: {
      "Accept": "application/json",
      'app_id': 'TDK',
      'app_key': 'swordfish'
    }
  };
  function callback(error, response, body) {
    console.log(response.statusCode);
    if (error) {
      console.log(error)
          }
    if (!error && response.statusCode == 200) {
      var word = JSON.parse(body);
      console.log(word);
      admin.firestore().collection('Users').doc(context.params.userID).collection('English_American').doc('Word_Response').set({
        'metadata': word.metadata,
        'results': word.results
      })
       .then(function() {
        console.log("Document written.");
      })
      .catch(function(error) {
        console.log("Error writing document: ", error);
      })
    }
  }
  request(options, callback);
} else {
  console.log("change.after.data().word === undefined");
}
return 0;

});

Вот журнал для одного вызова функции:

12:55:12.780 PM oxford_English_US { metadata: { provider: 'Oxford University Press' }, results: [ { id: 'to', language: 'en', lexicalEntries: [Object], type: 'headword', word: 'to' } ] }
12:55:12.480 PM oxford_English_US 200
12:55:09.813 PM oxford_English_US Function execution took 3888 ms, finished with status: 'ok'
12:55:09.739 PM oxford_English_US bcmrZDO0X5N6kB38MqhUJZ11OzA3
12:55:09.739 PM oxford_English_US { word: 'to' }
12:55:09.732 PM oxford_English_US { word: 'have' }
12:55:05.926 PM oxford_English_US Function execution started

Функция выполняется за четыре секунды.Через три секунды после завершения функции возвращается код состояния «200» с данными.Данные никогда не записываются в Firestore.

Похоже, что облачная функция не ожидает ответа HTTP.

Вот еще один журнал функций, в котором облачная функция, по-видимому, завершила выполнение перед отправкой HTTP-запроса:

  1:02:29.319 PM oxford_English_US Function execution took 3954 ms, finished with status: 'ok'
  1:02:29.218 PM oxford_English_US bcmrZDO0X5N6kB38MqhUJZ11OzA3
  1:02:29.218 PM oxford_English_US { word: 'to' }
  1:02:29.213 PM oxford_English_US { word: 'the' }
  1:02:25.365 PM oxford_English_US Function execution started

Есть ли лучший Node-модуль для отправки HTTP-запросов?request имеет такой синтаксис:

request(options, callback);

Я бы предпочел вернуть обещание вместо обратного вызова.

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

Ваша облачная функция Google всегда должна возвращать обещание.Если вы не вернете обещание, вы столкнетесь с состоянием гонки, при котором контейнер приложения может быть сорван до завершения выполнения кода.

Из кода вашего примера:

exports.oxford_English_US = functions.firestore.document('Users/{userID}/English_American/Word_Request').onUpdate((change, context) => {

  return new Promise(function(resolve, reject) {
      // put your code here and resolve() or reject() based on outcome
  });

}

Отканал Firebase YouTube (2. Фоновые триггеры - вернуть обещание) «Вы должны вернуть Обещание, которое становится выполненным или отклоненным, когда ожидающая работа в этой функции завершена. Это позволяет облачным функциям знать, когда можно безопасно очистить вызов функции иперейти к следующему. "

https://youtu.be/652XeeKNHSk?t=44s

0 голосов
/ 26 апреля 2018

Я изменил Node-модуль request на request-promise.Это выполняется надежно и быстро сейчас.Вот мой новый код:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const rp = require('request-promise');

admin.initializeApp();

exports.oxford_English_US = functions.firestore.document('Users/{userID}/English_American/Word_Request').onUpdate((change, context) => {
  if (change.after.data().word != undefined) {
    let options = {
      uri: 'https://od-api.oxforddictionaries.com/api/v1/entries/en/' + change.after.data().word + '/pronunciations%3Bregions%3Dus',
      headers: {
        "Accept": "application/json",
        'app_id': 'TDK',
        'app_key': 'swordfish'
      },
      json: true
    };

    rp(options)
    .then(function (word) {
      admin.firestore().collection('Users').doc(context.params.userID).collection('English_American').doc('Word_Response').set({
        'metadata': word.metadata,
        'results': word.results
      })
      .then(function() {
        console.log("Document written.");
      })
      .catch(function(error) {
        console.log("Error writing document: ", error);
      })
    })
    .catch(function (error) {
      console.log(error);
    })
  } else {
    console.log("change.after.data().word === undefined");
  }
  return 0;
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...