Функция вернула неопределенное, ожидаемое обещание или значение и не может удалить старые данные из базы данных firebase с помощью облачных функций - PullRequest
0 голосов
/ 02 ноября 2019

Я пытаюсь удалить несколько узлов в моей базе данных, которые старше 12 часов. Я использую функцию pub / sub для запуска этого события. Я не знаю, действительно ли мой код зацикливается на всех узлах, поскольку я не использую триггеры базы данных onWrite, onCreate для определенных. ВотПример изображения базы данных

enter image description here

это код публикации / подписки

 exports.deletejob = functions.pubsub.topic('Oldtask').onPublish(() => {

           deleteOldItem();
})

и функция deleteOldItem

function deleteOldItem(){
const CUT_OFF_TIME =  12 * 60 * 1000; // 12 Hours in milliseconds.
//var ref = admin.database().ref(`/articles/${id}`);
const ref = admin.database().ref(`/articles`);
 const updates = {};
ref.orderByChild('id').limitToLast(100).on('value', function (response) {
    var index = 0;

   response.forEach(function (child) {
    var element = child.val();

     const datetime = element.timestamp;

         const now = Date.now();

         const cutoff = now - datetime;

if (CUT_OFF_TIME < cutoff){

     updates[element.key] = null;
}

  });
//This is supposed to be the returened promise
 return ref.child(response.key).update(updates);

});

Если я что-то не так делаю, я хотел бы знать. Pub / sub запускается с помощью JobScheduler, уже настроенного на Google Cloud Scheduler

1 Ответ

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

В вашем коде было несколько проблем, которые доставляли вам проблемы.

  • Обработка обещаний была неправильной. В частности, ваша функция верхнего уровня никогда не возвращала обещание, она просто вызывала deleteOldItems().
  • Вы должны использовать форму обещания once() вместо вызова on() с обратным вызовом, поскольку вы нев этом случае вы хотите установить прослушиватель, вам нужен только один раз, и вы хотите обрабатывать его как часть цепочки обещаний.
  • Чтобы удалить узлы, вы должны вызвать remove() для ссылкик этому узлу. Это также дает вам обещание использовать здесь.
  • Вы не правильно рассчитали 12 часов в миллисекундах, вы рассчитали 12 минут в миллисекундах:)

Вот что я нашелс участием. Он использует функцию http вместо функции pubsub, а также добавляет инструкцию log для моего тестирования, но нужная вам модификация должна быть тривиальной / очевидной (просто измените прототип и удалите ответ после deleteOldItems, но убедитесь, что выпродолжайте возвращать результат deleteOldItems()):

const functions = require('firebase-functions');
const admin = require('firebase-admin');

function deleteOldItems() {
  const CUT_OFF_TIME =  12 * 60 * 60 * 1000; // 12 Hours in milliseconds.
  const ref = admin.database().ref('/articles');
  return ref.orderByChild('id').limitToLast(100).once('value')
    .then((response) => {
      const updatePromises = [];
      const now = Date.now();

      response.forEach((child) => {
        const datetime = child.val().timestamp;
        const cutoff = now - datetime;

        console.log(`processing ${datetime} my cutoff is ${CUT_OFF_TIME} and ${cutoff}`);

        if (CUT_OFF_TIME < cutoff){
          updatePromises.push(child.ref.remove())
        }
      });

      return Promise.all(updatePromises);
    });
}

exports.doIt = functions.https.onRequest((request, response) => {
    return deleteOldItems().then(() => { return response.send('ok') });
}

Хотя я не проверял его, я почти уверен, что он будет работать, чтобы включить в ваш исходный вызов функции облачный планировщик:

exports.deletejob = functions.pubsub.topic('Oldtask').onPublish(() => {
    return deleteOldItems();
})

Конечно, это все еще сложнее, чем нужно, так как заказ по id на самом деле ничего вам здесь не дает. Вместо этого, почему бы просто не использовать запрос, чтобы вернуть самые ранние элементы до времени отключения (например, те, которые вы хотите удалить)? Я также переключился на limitToFirst, чтобы исключить самые ранние записи, что кажется более естественным и обеспечивает справедливость:

function deleteOldItems() {
  const cutOffTime =  Date.now() - (12 * 60 * 60 * 1000); // 12 Hours earlier in milliseconds.
  const ref = admin.database().ref('/articles');
  return ref.orderByChild('timestamp').endAt(cutOffTime).limitToFirst(100).once('value')
    .then((response) => {
      const updatePromises = [];

      response.forEach((child) => {
          updatePromises.push(child.ref.remove())
      });

      return Promise.all(updatePromises);
    });
}

Если вы делаете это более чем на несколькихэлементы, конечно, вы, вероятно, захотите добавить индекс в поле отметки времени, чтобы запрос диапазона был более эффективным.

...