Запускать задание Cron каждые 30 минут после события onCreate Firestore - PullRequest
2 голосов
/ 06 августа 2020

Я хочу иметь задание / планировщик cron, которое будет запускаться каждые 30 минут после возникновения события onCreate в Firestore. Задание cron должно запускать облачную функцию, которая выбирает документы, созданные за последние 30 минут, проверяет их на соответствие схеме json и сохраняет их в другой коллекции. Как мне этого добиться, написав такой планировщик программно? Что также могло бы быть отказоустойчивым механизмом и своего рода постановкой в ​​очередь / отслеживанием документов, созданных до того, как задание cron будет запущено для pu sh их в другую коллекцию.

Ответы [ 3 ]

2 голосов
/ 06 августа 2020

Вы можете запустить облачную функцию в событии Firestore Create, которое будет планировать облачную задачу через 30 минут. У этого будет механизм постановки в очередь и повторных попыток.

2 голосов
/ 06 августа 2020

Создание очереди с помощью Firestore просто и идеально подходит для вашего случая использования. Идея состоит в том, чтобы записать задачи в коллекцию queue со сроком выполнения, который затем будет обработан при наступлении срока.

Вот пример.

  1. Каждый раз, когда происходит ваше начальное событие onCreate для вашей коллекции, напишите документ со следующими данными в коллекцию tasks:
    duedate: new Date() + 30 minutes
    type: 'yourjob'
    status: 'scheduled'
    data: '...' // <-- put whatever data here you need to know when processing the task

Попросите работника регулярно забирать доступную работу - например, каждую минуту в зависимости от ваших потребностей
// Define what happens on what task type
const workers: Workers = {
  yourjob: (data) => db.collection('xyz').add({ foo: data }),
}


// The following needs to be scheduled

export const checkQueue = functions.https.onRequest(async (req, res) => {
  // Consistent timestamp
  const now = admin.firestore.Timestamp.now();
  // Check which tasks are due
  const query = db.collection('tasks').where('duedate', '<=', new Date()).where('status', '==', 'scheduled');
  const tasks = await query.get();
  // Process tasks and mark it in queue as done
  tasks.forEach(snapshot => {
    const { type, data } = snapshot.data();
    console.info('Executing job for task ' + JSON.stringify(type) + ' with data ' + JSON.stringify(data));
    const job = workers[type](data)
      // Update task doc with status or error
      .then(() => snapshot.ref.update({ status: 'complete' }))
      .catch((err) => {
        console.error('Error when executing worker', err);
        return snapshot.ref.update({ status: 'error' });
      });

    jobs.push(job);
  });
  return Promise.all(jobs).then(() => {
    res.send('ok');
    return true;
  }).catch((onError) => {
    console.error('Error', onError);
  });
});

У вас есть разные варианты запуска проверки очереди, если есть задача, которая должна быть выполнена :

  • Использование функции, вызываемой по протоколу http, как в примере выше. Это требует, чтобы вы регулярно выполняли http-вызов этой функции, чтобы она выполнялась и проверяла, есть ли задача, которую нужно выполнить. В зависимости от ваших потребностей вы можете сделать это с собственного сервера или использовать такую ​​службу, как cron-job.org , для выполнения вызовов. Обратите внимание, что вызываемая функция HTTP будет общедоступна и потенциально, другие также могут ее вызвать. Однако, если вы сделаете свой проверочный код идемпотентным, это не должно быть проблемой.
  • Используйте Firebase "внутренний" параметр cron , который использует Cloud Scheduler внутренне. Используя это, вы можете напрямую запустить проверку очереди:
    export scheduledFunctionCrontab =
    functions.pubsub.schedule('* * * * *').onRun((context) => {
        console.log('This will be run every minute!');
        // Include code from checkQueue here from above
    });

Использование такой очереди также делает вашу систему более надежной - если что-то пойдет не так, вы не потеряете задачи, которые каким-то образом могли бы существовать в памяти, но до тех пор, пока они не помечены как обработанные, fixed worker возьмет их и повторно обработает. Это, конечно, зависит от вашей реализации.

1 голос
/ 06 августа 2020

Самый простой способ - добавить поле created с меткой времени, а затем запустить запланированную функцию в заранее определенный период (скажем, раз в минуту) и выполнить определенный код для всех записей, где created >= NOW - 31 mins AND created <= NOW - 30 mins ( псевдокод). Если ваши требования к точности времени не слишком высоки, это должно работать в большинстве случаев.

Если это не соответствует вашим потребностям, вы можете добавить облачную задачу (продукт Google Cloud). Подробности указаны в этой хорошей статье .

...