Пишем cron микросервис с AWS Lambda и Serverless

Разработка /
Недавно мы столкнулись с ситуацией, когда нам понадобилось создать задание cron присоединять всех из нашей базы данных пользователей находящихся в конце своего триального периода, в базу данных customer.io. Задание cron написать легко, сложно его по уму настроить.
Вариантов несколько:
  • можно редактировать /etc/crontab на сервере;
  • если используете heroku, то можно сделать это с помощью их планировщика(Scheduler);
  • или вы можете использовать реализации cron на предпочтительном вам языке программирования.
Cron задание которое нам было нужно, не было связано с нашим кодом приложения, поэтому не было большого желания держать его на рабочем сервере, а использовать для процесса работающего раз в день и всего 10 секунд, отдельный сервер, кажется несколько расточительно. И вот что мы придумали.
Использовать /
AWS Lambda это облачная вычислительная платформа, которая позволяет загрузить какой либо код, и исполнять его в облачном окружении. Прелесть сего метода в том, что платите вы только за время когда ваш код работает(с шагом 100 мс).
В сочетании с АМС ScheduledEvents это стало идеальным решением для нас.

Serverless это фреймворк и утилита командной строки которая упрощает создание функций AWS Lambda через API более удобное, чем официальный модуль узла aws-sdk. Он имеет хорошую документацию для установки, и подробную инструкцию, как дать ему доступ к учетной записи AWS: Инструкция.

Микросервис создается следующими командами (необходимо также установить AWS):
npm i serverless -g  
serverless create --template aws-nodejs --path users-ending-trial  
cd users-ending-trial

Затем берём файл serverless.yml и добавим опционально время в которое вы намерены выполнять его:
service: users-ending-trial  
provider:  
  name: aws
  runtime: nodejs4.3
functions:  
  fetchTrialUsers:
    handler: handler.fetchTrialUsers
    events:
      # 10am every morning
      - schedule: cron(0 10 * * ? *)

Пропишем в handler.js следующее:
'use strict';

const mongo = require('mongodb').MongoClient;

const CUSTOMER_IO_KEY = process.env.CUSTOMER_IO_KEY;  
const CUSTOMER_IO_SECRET = process.env.CUSTOMER_IO_SECRET;  
const MONGO_READ_URL = process.env.MONGO_READ_URL;

const CustomerIo = require('customerio-node');

const cio = new CustomerIo(CUSTOMER_IO_KEY, CUSTOMER_IO_SECRET);

function getRelativeDate(offset) {  
  return new Date(new Date().setDate(new Date().getDate() + offset));
}

module.exports.fetchTrialUsers = (event, context, callback) => {  
  mongo.connect(MONGO_READ_URL, (err, db) => {
    db.collection('projects').find({ 'trial.trialEndsAt': { $gt: getRelativeDate(2), $lt: getRelativeDate(4) }, plan: 'free' }).toArray((err, projects) => {
      if (err) {
        console.error('Error reading projects from database');
        return callback(err);
      }

      Promise.all(projects.map((project) => {
        return cio.track(project.owner, { name: 'threeDaysLeft', data: { project } });
      })).then(() => {
        callback(null, projects.length);
      }, (e) => {
        console.error('Error tracking customers in customer.io', e);
        return callback(e);
      });

      db.close();
    });
  });
};

Чтобы тестировать работу локально выполняем:
serverless invoke local -f fetchTrialUsers

Чтобы развернуть в продакшн:
serverless deploy -f fetchTrialUsers

Для запуска используйте ту же команду что и для локального теста, только без local:
serverless invoke -f fetchTrialUsers

И вуаля! Теперь это должно запускать ваш исполняемый код на AWS Lambda каждый день в назначенное время. Этот простой, но очень мощный способ работы, который позволяет сосредоточиться на коде, а не на инфраструктуре, которая требуется для его запуска.

Источник на английском: https://blog.readme.io/
0 комментариев
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.