Redis и BullMQ: фоновые задачи «Импортёра»
Проект «Импортёр» принимает вымышленное поступление товаров из одного CSV. Лампа, блокнот и карандаш сохраняют SKU на протяжении курса; количество пакета прибавляется к текущему остатку. Сначала отделяем кеш от источника, задаём TTL и поколение каталога. Затем вводим лимит постановки, контракт задачи BullMQ, отдельный worker, retries и атомарный идемпотентный пакет. Последние главы объясняют stalled, конкуренцию, прогресс и retention.
Нужны основы JavaScript, async/await, модулей, HTTP и представление о ключах Redis. Среда: Node.js 24 LTS, Express 5.2.1, BullMQ 6.3.12, ioredis 5.11.1 и отдельный локальный Redis 7.2+. Версии библиотек подтверждены по release-tag package.json. Redis требуется политика noeviction; долговечность зависит от persistence и согласованного резервирования, а не от имени библиотеки очереди.
CSV является ограниченным учебным диалектом без кавычек и переносов внутри поля, максимум 100 строк. Dataset разрешён по белому списку, произвольный путь не принимается. Основной каталог и бизнес-отметки находятся в Redis; это демонстрация малого пакета, для реального учёта обычно нужна отдельная бизнес-БД и журнал.
Состояния 6–7 намеренно показывают неидемпотентную запись, чтобы объяснить ошибку повтора. С урока 8 Lua согласует остатки, поколение и отметку одного batchId. Отметка бессрочна; удаление завершённой job по retention не разрешает повторное поступление. Атомарное исполнение не означает rollback при любой ошибке Lua. Все HTTP-ресурсы локальные и не реализуют production-вход или проверку владельца задачи.
Все примеры имеют статус not_run. Зависимости не устанавливались, приложения, Redis и тесты не запускались; сборка учебного приложения и деплой не выполнялись. Ответы, состояния интерфейса и количества в уроках являются ожидаемыми, а не полученными. Lockfile не создавался без установки пакетов.
Последовательность уроков
| Урок | Новый результат |
|---|---|
| 1. Кеш каталога и источник данных | Прочитать вымышленный каталог через Redis-кеш. |
| 2. Срок жизни кеша | Ограничить время хранения кешированной копии. |
| 3. Инвалидация и поколение каталога | Менять ключ кеша вместе с версией основных данных. |
| 4. Атомарный лимит запросов | Ограничить постановку задач счётчиком с TTL. |
| 5. Постановка импорта в BullMQ | Задать контракт задачи и устойчивый jobId. |
| 6. Воркер и обработка CSV | Отделить HTTP-ответ от добавления остатков товаров. |
| 7. Повтор задачи и постоянная ошибка | Различать временный сбой и непригодные данные. |
| 8. Идемпотентное изменение остатков | Записать остатки и отметку импорта одним Lua-скриптом. |
| 9. Зависшая задача и потеря блокировки | Объяснить повтор выполнения после потери воркера. |
| 10. Конкуренция воркеров | Ограничить параллельность и сохранить атомарность результата. |
| 11. Прогресс и наблюдение за задачей | Показать состояние задачи и события QueueEvents. |
| 12. Хранение результатов и контракт выпуска | Ограничить retention, закрыть соединения и описать эксплуатацию. |
Скачать полные снимки проекта. Распакуйте архив в новую отдельную папку redis-jobs-lab/, затем выберите один каталог stages/NN. Каждый номер самодостаточен: не объединяйте файлы разных состояний. Внутри есть README с предпосылками, инструкциями читателю и конкретными ограничениями. Архив не содержит зависимостей, сборок, .git, секретов и реальных данных.
Все снимки используют одинаковые учебные ключи и очередь. Переход между ними требует свежего отдельного окружения либо осознанной изоляции; не запускайте разные ступени одновременно против важного Redis. Сам архив не очищает базу и ничего не запускает.