Магазин, который обслуживает себя сам: воркфлоу, подписчики и задачи по расписанию
Разбираю на примере Medusa, из каких кирпичей собирается магазин, который делает рутину без человека: воркфлоу, подписчики на события, задачи по расписанию и собственные API-ручки.
Любой магазин обрастает рутиной. Пришёл заказ — надо дёрнуть склад. Создали товар — надо отправить его в фид. Наступила ночь — надо пересчитать остатки и почистить брошенные корзины. Обычно это делает человек руками или набор скриптов, про которые через полгода никто не помнит.
В Medusa под эту рутину есть четыре штатных механизма. Я разберу каждый: что он умеет, где лежит в проекте и когда его брать.
Воркфлоу: сценарий, разбитый на шаги
Воркфлоу — это последовательность запросов и действий, которая доводит задачу до конца. Живёт в src/workflows. Смысл в том, что сценарий разбивается на шаги, и каждый шаг — отдельная именованная функция.
import {
createStep,
createWorkflow,
WorkflowResponse,
StepResponse,
} from "@medusajs/framework/workflows-sdk"
const step1 = createStep("step-1", async () => {
return new StepResponse(`Hello from step one!`)
})
Почему это лучше одной большой функции: шаги видно по именам, их можно переиспользовать в разных сценариях, и логика перестаёт быть монолитом, который страшно трогать.
Сюда просятся длинные бизнес-цепочки: обработка заказа, синхронизация с внешней системой, начисление бонусов. Всё, что состоит из нескольких «сначала это, потом то».
Подписчики: реакция на событие
Подписчик обрабатывает события, которые приложение генерирует само. Файл кладётся в src/subscribers.
import { type SubscriberConfig } from "@medusajs/framework"
export default async function productCreateHandler() {
console.log("A product was created")
}
Файл экспортирует две вещи: саму функцию-обработчик и конфиг, который говорит, на какое событие подписываемся. Дальше приложение вызывает функцию каждый раз, когда событие происходит.
Это механика «случилось — отреагировали». Создали товар — ушёл вебхук в аналитику. Оформили заказ — улетело письмо. Отменили — вернулись остатки. Подписчик хорош тем, что не лезет в основной код: продуктовая логика ничего не знает про почту и аналитику, она просто сообщает о факте.
Задачи по расписанию: то, что делается по часам
Задача по расписанию — функция, которая выполняется через заданный интервал в фоне. Лежит в src/jobs.
import { MedusaContainer } from "@medusajs/framework/types"
export default async function myCustomJob(container: MedusaContainer) {
// ...
}
В функцию приходит контейнер приложения — через него достаются сервисы и данные. Рядом с функцией задаётся конфиг с расписанием.
Зачем это нужно: ночная выгрузка каталога, пересчёт цен, напоминания по брошенным корзинам, проверка зависших платежей. Всё, у чего нет события-триггера и что просто должно случаться регулярно.
API Route: дверь для внешнего мира
Собственная ручка — это REST-эндпоинт. Файл создаётся в /src/api, называется строго route.ts или route.js, а путь до него становится адресом эндпоинта.
import type { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
export async function GET(
// ...
)
Положили файл в src/api/store/hello-world/route.ts — получили GET /store/hello-world. Функция называется по HTTP-методу.
Через ручки в систему стучится всё внешнее: фронт, мобильное приложение, чужая CRM, вебхуки платёжки.
Как это складывается в самообслуживание
В связке получается простая схема:
- Воркфлоу — где живёт логика. Один сценарий, много шагов.
- Подписчик — кто запускает воркфлоу, когда что-то произошло внутри магазина.
- Задача по расписанию — кто запускает воркфлоу, когда наступило время.
- API Route — кто запускает воркфлоу, когда постучались снаружи.
Логика пишется один раз в воркфлоу. Дальше три разных повода её вызвать. Это ключевая мысль: подписчики, крон и ручки — способы дёрнуть один и тот же сценарий, а сценарий про них ничего не знает.
С чего начинать на практике
Советую заходить от боли. Выпишите операции, которые сейчас делаются руками, и рассортируйте:
- Что происходит после какого-то действия в магазине — это подписчик.
- Что делается регулярно по времени — это задача по расписанию.
- Что дёргают снаружи — это API Route.
- Что внутри любого из трёх пунктов состоит из нескольких шагов — это воркфлоу.
Первым автоматизируйте то, что повторяется чаще всего и ошибается больнее всего. Обычно это выгрузки и уведомления. Одна задача по расписанию плюс один воркфлоу из двух шагов — уже рабочий результат, который видно в первый же день.
И отдельно про порядок: пишите шаги так, чтобы повторный запуск не ломал данные. Крон однажды сработает дважды, вебхук придёт повторно — это нормальная жизнь продакшена. Проверка «я это уже делал?» в начале шага стоит пять строк и экономит вечер разбирательств.
Автоматизация для бизнеса
Вторая сторона исследования: собираю под бизнес ИИ-агентов и автоматизации, которые работают и с клиентами, и с командой. Система остаётся у вас в работе и под вашим управлением.