Создание планировщика электронной почты с помощью функций Vercel и qStash

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

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

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

Высокоинтегрированные облачные провайдеры, такие как AWS или Google, могут предложить очереди с ценой по требованию, но это не всегда возможно.

Именно здесь в игру вступает qStash — новый сервис очередей от Upstash. Это бессерверная очередь, в которой вы платите только за то, что используете. Она поддерживает доставку на одну или несколько конечных точек HTTP, дедупликацию на основе идентификаторов или хэша контента, а также доставку по расписанию.

В этой статье мы проверим, на что способен qStash, создав на его основе планировщик электронной почты. В качестве облачного провайдера в этом учебнике будет выбран Vercel. Итак, поехали!

Предварительные условия

Чтобы следовать этому руководству, вам понадобятся учетные записи для трех сервисов:

  • GitHub
  • Upstash
  • [Vercel(https://vercel.com/signup)

Настройка приложения Next.js

Первым шагом будет создание проекта Next.js. Для этого выполните следующую команду:

$ npx create-next-app@latest
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем перейдите в папку нового проекта.

Установка зависимостей

Хотя сервис qStash используется через HTTP API, пакет TypeScript делает работу с ним более доступной. Для отправки писем вы будете использовать пакет nodemailer. Установите их с помощью NPM:

$ npm i @upstash/qstash nodemailer
Войдите в полноэкранный режим Выйти из полноэкранного режима

Создание маршрута API расписания

Next.js поставляется с превосходной интеграцией для функций Vercel. Создание маршрута API будет автоматически выполняться внутри бессерверной функции Vercel без дополнительных изменений кода. Для этого создайте новый файл JavaScript по адресу pages/api/schedule.js со следующим содержимым:

import { Client } from "@upstash/qstash"

const qstashClient = new Client({
  token: process.env.QSTASH_TOKEN
})

export default async function handler(request, response) {
  if (request.method !== "POST")
    return response.status(404).end()

  const qstashResponse = await qstashClient.publishJSON({
    url: `https://${request.headers.host}/api/notify`,
    body: request.body,
    notBefore: request.query.timestamp,
  })

  response.status(201).send(qstashResponse)
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Сначала вы инициализируете клиент qStash с помощью токена из Upstash. Лучшая практика предлагает поместить токен в переменные окружения, которые зашифрованы в Vercel. (Вы установите эти переменные позже, когда закончите часть кода).

Далее идет собственно функция handler. Она проверяет, что функция была вызвана через метод POST, и приступает к извлечению содержимого из запроса, чтобы использовать его в qStash.

qStash использует поле url в качестве цели для запланированного сообщения. Мы хотим, чтобы оно вызывало другой маршрут API из нашего приложения Next.js, но домен может меняться между развертываниями Vercel; мы будем использовать поле заголовка Host, чтобы получить правильный URL.

Поле body — это просто то, что содержит наш API-запрос в своем теле.

Поле notBefore принимает временную метку Unix в качестве даты, когда мы хотим отправить письмо.

Чтобы связать все вместе, пользователь отправляет запрос с текстовым телом и параметром запроса timestamp в наш API-маршрут, а функция Vercel передает его в qStash.

Создание маршрута API Notify

Теперь, когда мы получили наши сообщения, запланированные в qStash, нам нужен маршрут для преобразования их в электронные письма и их рассылки. Для этого создайте файл по адресу pages/api/notify.js, который будет содержать:

import nodemailer from "nodemailer"
import { verifySignature } from "@upstash/qstash/nextjs"

export const config = {
  api: { bodyParser: false },
}

export default verifySignature(handler, {
  currentSigningKey: process.env.QSTASH_CURRENT_SIGNING_KEY,
  nextSigningKey: process.env.QSTASH_NEXT_SIGNING_KEY,
})

async function handler(request, response) {
  const emailAccount = await nodemailer.createTestAccount()

  const transport = nodemailer.createTransport({
    host: "smtp.ethereal.email",
    auth: emailAccount,
  })

  await transport.sendMail({
    from: '"qStash" <qstash@upstash.com>',
    to: "jane.doe@example.com",
    subject: "Notification from qStash",
    text: request.body,
  })

  response.send()
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Сначала мы экспортируем объект config, чтобы сообщить Next.js, что он не должен разбирать тело. Next.js разбирает тело по умолчанию, но для проверки подписи запроса qStash нам нужно сырое/неразобранное тело.

Служба qStash подписывает все запросы, чтобы гарантировать, что вы обрабатываете только действительные сообщения. Промежуточному ПО нужны ключи подписи из Upstash. Опять же, мы предполагаем, что они будут находиться в переменных окружения.

Функция обработчика создает тестовый аккаунт на ethereal.email, простой тестовый сервис для nodemailer, и пытается отправить с него письмо. В своем собственном приложении вы можете заменить этот сервис на почтовый сервис по вашему выбору.

Отправка кода на GitHub

Vercel будет собирать и развертывать ваше приложение каждый раз, когда вы будете отправлять новый коммит на GitHub, но для этого оно должно быть сначала размещено на GitHub. Создание репозиториев GitHub и размещение в них кода выходит за рамки данной статьи, но в Интернете можно найти хорошие объяснения.

Создание проекта Vercel

Вам нужно создать новый проект на Vercel, импортировав репозиторий GitHub из предыдущего шага.

При создании проекта не забудьте внести учетные данные qStash в нужные переменные окружения. На рисунке 1 показано, где их можно найти в Upstash Console.

Напоминаем, что переменные должны иметь следующие имена:

  • QSTASH_TOKEN
  • QSTASH_CURRENT_SIGNING_KEY
  • QSTASH_NEXT_SIGNING_KEY

После создания проекта Vercel загрузит последнюю версию с GitHub, соберет ваше приложение и развернет его на своей инфраструктуре.

Тестирование приложения

Чтобы протестировать приложение, вы должны получить правильный домен от Vercel после завершения развертывания. На рисунке 2 показано, где его можно найти.

Чтобы отправить запрос к вашему приложению, вы можете использовать инструмент cURL CLI:

$ curl -X POST 
  -H "Content-Type: text/plain" 
  -d "Hello!" 
  "https://<APP_DOMAIN>.vercel.app/api/schedule?timestamp=<TIMESTAMP>" 
Войти в полноэкранный режим Выйти из полноэкранного режима

Замените APP_DOMAIN и TIMESTAMP соответствующим образом.

Вы можете проверить доставку вашего сообщения в Upstash Console, как показано на рисунке 3.

Резюме

Бессерверная разработка приложений — это склеивание сервисов вместе. Либо вы позволяете своим функциям напрямую вызывать другие функции, либо вам нужно поместить между ними другой сервис.

Новый сервис бессерверной очереди Upstash приходит на помощь с простым интерфейсом и платной ценой.

Он на 100% построен на безэталонных HTTP-запросах и предназначен для:

  • Бессерверных функций (AWS Lambda …)
  • Cloudflare Workers
  • Fastly Compute@Edge
  • Next.js, включая edge
  • Deno
  • Клиентские веб-/мобильные приложения
  • WebAssembly
  • другие среды, где HTTP предпочтительнее TCP.

Я вызвал у вас интерес?

Попробуйте; первые 50 запросов в день — за счет заведения!

Оцените статью
devanswers.ru
Добавить комментарий