Назад в архив
IV. Клиентские проекты и логистические платформывитриналидклиент анонимизирован

Arryt — Courier Logistics v1

Полноценная платформа управления курьерской доставкой (для Restaurant chain (UZ)/Restaurant chain (UZ)): бэкенд на Bun/Elysia с диспетчеризацией заказов в реальном времени, очереди BullMQ, OLAP-аналитика на DuckDB через CDC-репликацию из Postgres по gRPC, админ-панель на Refine и мобильное приложение курьера на Flutter.

Статус
поддерживается
Период
2023-11-04 → 2025-03-09
AI-сессий
Стек
Языки
TypeScriptDartSQL
Фреймворки · Инфра
Elysia (Bun)Apollo GraphQLDrizzle ORMBullMQDuckDBgRPCRefine + Ant DesignFlutter/BLoCOpenTelemetry
§01

Обзор

  • Что это: монорепозиторий системы доставки еды. Принимает заказы, распределяет их по курьерам в реальном времени (учитывая геолокацию, очереди, смены, «дневной гарант»), интегрируется с Yandex Dostavka как fallback-сервисом, рассчитывает зарплаты/балансы курьеров, рейтинги и отчёты. Семь сабсервисов: api (бэкенд на Elysia), queue (воркеры BullMQ), crons (задачи по расписанию), duck_api (OLAP-аналитика на DuckDB), transfer_db (миграция данных), admin (панель на Refine), mob (приложение курьера на Flutter).
  • Тип / статус / роль: web-app (распределённая система + мобилка) · maintained (жил ~1.5 года, активно) · lead — пользователь co-lead с Ilhombek (≈78 против 59 коммитов).
  • Окно активности: 2023-11-04 → 2025-03-09. Долгоживущая продакшн-система с эволюцией стека внутри: миграции Prisma→Drizzle и NestJS-подобного слоя→Elysia видны в крупных «перетряхивающих» коммитах (92 файла +2962/−3418, 35 файлов +2386/−2924, 29 файлов +2002/−2341).
§02

Стек

  • Языки: TypeScript (бэкенд/админка), Dart (мобилка на Flutter), SQL (Postgres + DuckDB).
  • Фреймворки/библиотеки:
  • *Бэкенд (api):* Bun + Elysia (кластеризация через node:cluster, 4 воркера в проде), Apollo GraphQL (@elysiajs/apollo) + REST, Drizzle ORM (drizzle-typebox, drizzle-zod), Postgres (postgres/pg), BullMQ + Bull, ioredis, jose (JWT), bcrypt, geolib (гео-математика), dayjs (utc/timezone), lodash/radash, @evan/duckdb + gRPC-клиент к duck_api.
  • *Аналитика (duck_api):* DuckDB (duckdb-async) с подключением к Postgres через расширение (ATTACH … TYPE POSTGRES), pg-logical-replication (CDC), Kafka (kafkajs + node-rdkafka), Hono + Elysia, gRPC-сервер (arryt.proto, сервис Transactions).
  • *Админка:* Refine (@refinedev/antd, @refinedev/graphql, kbar) + Ant Design 5, TanStack Query, React 18, Vite, Yandex Maps (react-yandex-maps), экспорт в Excel/PDF, react-hook-form, i18next.
  • *Мобилка (mob):* Flutter + flutter_bloc, auto_route, Dio + HTTP/2, Firebase (analytics/crashlytics/messaging/performance/remote_config), flutter_background_service (фоновый трекинг GPS курьера), flutter_local_notifications, chatview (чат), inappwebview.
  • Инфра/деплой: рантайм Bun (bun.lockb в каждом пакете), PM2 (queue/pm2.config.js), кластеризованный API. Redis для очередей и кэша. Observability: OpenTelemetry (@opentelemetry/sdk-node, OTLP-экспортёр), Prometheus (prom-client), Pino + pino-loki (логи в Grafana Loki).
  • Данные: Postgres (OLTP, основная БД через Drizzle), DuckDB (OLAP/аналитика, отдельный сервис), Redis (очереди + кэш). gRPC как транспорт между api и duck_api.
  • Заметный тулинг: кастомный Bun-плагин (proto.ts) для импорта .proto напрямую как модулей; кастомный слой parseFilterFields/parseSelectFields для динамических Drizzle-запросов из фильтров админки.
§03

Что реализовано

NOTE: сообщения коммитов в этом репозитории в основном мусорные («dddd», «dd», «ddd», «fff», «solved») — выводы сделаны по коду, а не по сообщениям.

  • Миграция стека: крупные коммиты с почти равными +/− (92 файла +2962/−3418 и т. п.) — порт бэкенда на Bun/Elysia + Drizzle (в api до сих пор остаётся артефакт prisma/ и ~schema.gql, а @prisma/client соседствует с drizzle — переходный период).
  • Диспетчеризация заказов: построен движок назначения курьеров на BullMQ (~18 очередей/воркеров): new_order_notify, try_assign_courier, push_courier_to_queue, set_queue_last_courier, change_courier, clear_courier, order_complete, change_status, store_location (GPS курьера), send_notification, order_index (поисковый индекс), try_set_daily_garant.
  • Интеграция с Yandex Dostavka: воркеры check_and_send_yandex + yandex_callback — авто-передача внешнему сервису, когда своего курьера нет.
  • OLAP-аналитика: сервис duck_api — зеркалирует таблицы Postgres в DuckDB + CDC через логическую репликацию/Kafka, отдаёт агрегаты (отчёты по выводам/транзакциям) через gRPC.
  • Отчёты и расчёты: crons/calculate_courier_performance.ts (ежемесячный рейтинг курьеров), balance_report_send.ts, send_courier_withdraws_report.ts; orders/controller.ts на 3054 строки — отчёты по гаранту, ценообразование доставки, сводки.
  • Мобильное приложение курьера: Flutter с фоновым GPS, пушами, чатом, архитектурой на BLoC.
  • Объём: 148 коммитов за ~16 месяцев силами двух основных разработчиков; пользователь — крупнейший контрибьютор (~78 коммитов, с учётом трёх его identity).
§04

Технические челленджи

Всё подтверждено по файлам/диффам:

  • OLTP→OLAP через DuckDB + CDC (duck_api/src/sync_duck.ts, arryt.proto, api/src/lib/duck_grpc.ts): тяжёлые аналитические запросы (история транзакций/выводов курьеров) вынесены из Postgres в DuckDB. Синхронизация использует нативное расширение DuckDB для Postgres (INSTALL postgres; ATTACH '…' AS db (TYPE POSTGRES); CREATE TABLE … AS FROM db.<table>) + стриминг дельты через pg-logical-replication и Kafka. Результаты возвращаются в основной API по gRPC (Transactions.getWithdrawTransactions). → Демонстрирует понимание разделения OLTP/OLAP, CDC и межсервисного gRPC — серьёзная data-engineering-работа.
  • Real-time диспетчеризация на очередях (queue/index.ts + 16 процессоров): ~18 пар Queue/Worker BullMQ поверх одного Redis, пайплайн назначения курьеров с очередью «последний курьер на терминал», fallback на Yandex, обновление кэша пользователей, индексация для поиска. → Проектирование event-driven системы с воркерами, разделёнными по ответственности.
  • Алгоритм ранжирования курьеров (crons/calculate_courier_performance.ts): разрешает граф «связанных терминалов» (getLinkedTerminalIds), батчем подтягивает все заказы и группирует через lodash, 3 параллельных запроса через Promise.all (count / avg-score / список для позиции в рейтинге), считает среднее время доставки и ранжирует курьеров (сортировка по числу доставок ↓, затем по среднему времени ↑). Пофакурьерный try/catch с continue — частичные сбои не роняют весь крон. → Продакшн-устойчивость + нетривиальная бизнес-логика.
  • Кластеризованный Elysia с observability (api/src/index.ts, app.ts, package.json): в проде 4 воркера, форкнутых через node:cluster, OpenTelemetry + экспорт по OTLP, метрики Prometheus (prom-client), структурированные логи в Loki (pino-loki). → Зрелый операционный подход.
  • Слой динамических запросов (api/src/lib/parseFilterFields.ts, parseSelectFields.ts, с sql.placeholder для prepared statements): админ-панель (Refine) шлёт фильтры/выборки полей → бэкенд безопасно собирает Drizzle-запросы. → Переиспользуемая абстракция вместо копипасты в каждом контроллере.
  • Кастомный Bun-плагин для .proto (proto.ts): Bun.plugin с onLoad-фильтром /\.proto$/, парсит protobuf и возвращает JS-модуль (лоадер "object"). → Нестандартное знание тулинга рантайма Bun.
  • Тяжёлый Flutter-клиент (mob/pubspec.yaml): фоновый GPS-сервис (flutter_background_service + disable_battery_optimization), полный стек Firebase, HTTP/2 через Dio, BLoC, auto_route, встроенный чат. → Реальное продакшн-мобильное приложение для курьеров, а не прототип.
§05

AI-разработка

  • Найдено сессий: 0 в локальной директории сессий Claude Code для этого проекта. Сессии есть для отдельного проекта new_arryt (и его мобильного сабдиректория) — это переписывание, покрытое в задаче #37, а не этот проект.
  • Что было сделано с AI: данных по этому репозиторию нет.
  • Паттерны AI-воркфлоу: отсутствуют — проект в основном написан до активного использования Claude Code (2023–2025, до перехода на new_arryt).
§06

Достижения и метрики

  • Масштаб: монорепозиторий из 7 сабсервисов, ~25 доменных модулей в api/src/modules/ (orders, couriers/users, terminals, delivery_pricing, daily_garant, order_transactions, manager_withdraw, brands, organizations, roles/permissions, work_schedules, chart, missed_orders, …).
  • Сложность ядра: orders/controller.ts — 3054 строки бизнес-логики; ~18 фоновых воркеров; версия api 1.0.50.
  • Реальная нагрузка: продакшн-доставка еды (Restaurant chain (UZ)/Restaurant chain (UZ)), интеграция с Yandex Dostavka, расчёт зарплат/балансов курьеров — система проработала ~1.5 года.
  • Полнота: бэкенд + аналитика + админка + мобилка — закрывает весь цикл доставки.
§07

Контрибьюторы

git shortlog · все ветки

  1. Dave9378
  2. i767175759
  3. root8
  4. shahzodsalimsakov2
  5. Macbook Pro1
5 контрибьюторов148 коммитов всего
Сейчас

Открыт к ролям Senior / Staff инженера и избранному фрилансу — продакшн-AI, платформы и full-stack разработка.

Связаться