сайт в бете
нашли баг? напишите
левин. записаться
весь блог

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

Разбираю на примере 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 — кто запускает воркфлоу, когда постучались снаружи.

Логика пишется один раз в воркфлоу. Дальше три разных повода её вызвать. Это ключевая мысль: подписчики, крон и ручки — способы дёрнуть один и тот же сценарий, а сценарий про них ничего не знает.

С чего начинать на практике

Советую заходить от боли. Выпишите операции, которые сейчас делаются руками, и рассортируйте:

  1. Что происходит после какого-то действия в магазине — это подписчик.
  2. Что делается регулярно по времени — это задача по расписанию.
  3. Что дёргают снаружи — это API Route.
  4. Что внутри любого из трёх пунктов состоит из нескольких шагов — это воркфлоу.

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

И отдельно про порядок: пишите шаги так, чтобы повторный запуск не ломал данные. Крон однажды сработает дважды, вебхук придёт повторно — это нормальная жизнь продакшена. Проверка «я это уже делал?» в начале шага стоит пять строк и экономит вечер разбирательств.

теги #medusa#автоматизация#воркфлоу#подписчики#cron#бэкенд
разберём вашу задачу

Автоматизация для бизнеса

Вторая сторона исследования: собираю под бизнес ИИ-агентов и автоматизации, которые работают и с клиентами, и с командой. Система остаётся у вас в работе и под вашим управлением.

подробнее и записаться цена по запросу

один разговор — и поймём, чем я могу помочь.

В эпоху ИИ человеку нужен человек. Сяду рядом и доведу до результата — встреча длится столько, сколько нужно. Без скрипта продаж и пакетов «за 999 000 ₽». Если пойму, что помочь не смогу, — скажу сразу.