Клієнт feedsync — фіди постачальників у прайс-листи маркетплейсів
Роль Solo Creator / Architect
Період Sep 2026
Стек
Go encoding/xml streaming XML/YML Prom.ua Rozetka Прайс-листи Синхронізація цін і залишків Імпорт/Експорт товарів MySQL SQLite Docker
feedsync — фіди постачальників у прайс-листи маркетплейсів preview

feedsync — фіди постачальників у прайс-листи маркетплейсів

Огляд

Незалежний проєкт: сервіс на Go, що перетворює прайс постачальника (YML/XML, CSV або JSON) на прайс-листи для Rozetka та Prom.ua і синхронізує таблицю товарів OpenCart. Мапінг категорій, конвертація валют, правила націнок (фіксовані, відсоткові, за діапазоном цін чи категорією, з округленням) і фільтр залишків — це конфігурація, а не код; кожна відхилена позиція потрапляє у звіт із правилом, яке вона порушила.

Результат: 25 000 позицій перетворюються на обидва прайс-листи приблизно за 1,5 с і ≈36 МБ пам’яті, кожен опублікований файл проходить незалежну повторну перевірку з 0 помилок, а повторна синхронізація OpenCart нічого не змінює (≈25 мс).


Справжня складність

Конвертувати XML просто. Складно те, що маркетплейс відхиляє — або мовчки викидає — весь прайс через кілька некоректних позицій, а фіди надто великі, щоб їх переглядати очима. Тому конвеєр побудований навколо принципу не публікувати неперевірений файл: фід читається потоком, кожна позиція перевіряється окремо, готовий файл перечитується з диска і перевіряється тим самим набором правил, і лише тоді замінює діючий.


Архітектура

Конвеєр feedsync: фід постачальника, обробка, перевірка, публікація, OpenCart

Один потоковий прохід читає фід, застосовує перетворення й пише кожну ціль у тимчасовий файл. Потім кожен файл повторно перевіряється з диска й атомарно перейменовується поверх опублікованого; невдалий запуск залишає попередній файл. Той самий прохід дає список оновлень для OpenCart — пакетні UPDATE … CASE в одній транзакції; змінюються лише рядки з новими значеннями.


Ключові інженерні рішення

Рішення Чому
Потоковий xml.Decoder, один DecodeElement на позицію Пам’ять не росте з розміром фіда: у 4 рази більше позицій — ≈2,5× пікової пам’яті (36 → 91 МБ на 100 000)
Повторна перевірка перечитує файл і ділить набір правил із передперевіркою Не довіряємо, що записувач записав те, що мав; перевіряється саме опублікований файл
Публікація через temp-файл і атомарне перейменування Маркетплейс ніколи не бачить напівзаписаний чи невдалий файл
Детерміновані ID позицій ([A-Za-z0-9]+ лишаються, інакше префікс + SHA-1) Той самий SKU постачальника щоразу дає той самий ID
Гроші як цілі копійки Жодного дрейфу float у націнках і округленні
Товар без залишку обнуляється в CMS, ціна не чіпається Мало прибрати його з прайсу — магазин продовжував би продавати те, чого в постачальника вже немає

Результати

Показник Результат
25 000 позицій (26 МБ) → Rozetka + Prom.ua ≈1,5 с, ≈36 МБ пікової пам’яті
100 000 позицій (105 МБ) 6–7 с, ≈91 МБ
Повторна перевірка опублікованих файлів 0 помилок в обох цілях
Відхилено для Rozetka 259 позицій, кожна з правилом (немає картинки, картинка не HTTPS, немає виробника) у report.json
Синхронізація OpenCart, MySQL 8.4 19 119 рядків у 39 пакетах, ≈0,7 с; повторний запуск: 0 змін, ≈25 мс

Юніт- та інтеграційні тести працюють під -race.


Підключення до вашого магазину

  • Фід постачальника: вкажіть у source.path файл або URL і source.format; новий формат — ще один читач.
  • Маркетплейси: кожен запис у targets формує один прайс-лист — спрямуйте out у каталог, який віддає ваш вебсервер.
  • CMS: рядок підключення до MySQL в opencart.dsn — і синхронізація цін і залишків починається з наступного запуску.
  • Розклад: feedsync convert -c config.yaml -every 30m.

Код: github.com/valpere/feedsync


Стек

Go · потоковий encoding/xml · MySQL · SQLite · Docker