Повечето WooCommerce интеграции са мисъл за последно. Инсталира се плъгин, веднъж седмично се импортира CSV и всички се надяват цените приблизително да съответстват на реалните наличности. Работи, докато не спре — а когато спре, продавате продукти на цени, непредлагани от наличности, каквито нямате.
Mr. Banny не можеше да работи по този начин. Те продават мебели за дома и открито пространство, доставяни от един основен доставчик на едро. Целият им каталог — над 50 000 продукта — идва от него. Цените се променят. Нивата на наличност се колебаят. Пристигат нови продукти. Спрените линии трябва да изчезват.
Трябваше им магазинът да отразява реалността, а не вчерашната реалност. Което означаваше синхронизация всеки час.
Ето как го изградихме.
Защо очевидните подходи не работят
Първият инстинкт при чуване на „импортирай 50 000 продукта” е да посегнеш към вградения импортер на WooCommerce или плъгин като WP All Import. Изпълни CSV импорт всеки час, готово.
Това не работи при мащаб по няколко причини.
Обработва всичко всеки път. Наивен импорт чете всеки ред, търси съответния продукт в базата данни и го обновява независимо дали нещо се е променило. 50 000 записа в базата данни на час за данни, предимно идентични с вече съществуващите. На жив магазин при реален трафик, това наситва връзките към базата данни и прави сайта бавен или неотзивчив по време на прозореца за синхронизация.
Не обработва изтриванията грациозно. Ако продукт изчезне от каталога на доставчика, импорт, обработващ само текущия файл, ще остави стария продукт активен безкрайно — показвайки го като наличен, когато повече не е.
Няма възстановяване след грешки. Когато импорт на 50 000 реда се провали на ред 30 000 поради деформиран запис или кратко прекъсване на базата данни, повечето импортери или спират изцяло, или произвеждат непоследователно частично състояние. Трябва да знаете какво е провалено, защо и какво е останало незавършено.
Изпълнява се като единичен блокиращ процес. PHP импорт скрипт, работещ 20-40 минути, е тикаща бомба на всеки споделен или слабо захранен хостинг. Таймаути, ограничения на паметта и конкурентен трафик — всичко заплашва изпълнението.
Нуждаехме се от нещо проектирано по различен начин от самото начало.
Архитектурата
Системата има три слоя: извличане, разлика и прилагане.
Слой 1: Извличане
Всеки час планиран фонов процес се свързва с API на доставчика и извлича текущия каталог. Изтегляме го в временна staging таблица в базата данни — не в живите WooCommerce таблици. Живият магазин е незасегнат на този етап.
Staging таблицата е опростена плоска структура: SKU на доставчика, цена, количество наличност, наименование, описание, пътека на категория и хеш от всички комбинирани полета. Този хеш е ключът към следващия слой.
Ако API повикването се провали — мрежово прекъсване, прекъсване при доставчика, деформиран отговор — процесът регистрира провала и излиза чисто. Предишните данни в staging таблицата остават незасегнати. Живият магазин продължава да обслужва от предишните данни. Получаваме предупреждение. Нищо не се счупва.
Слой 2: Разлика
Това е частта, правеща системата бърза.
Вместо да обработваме всичките 50 000 продукта при всяко изпълнение, сравняваме хеша за всеки SKU на доставчика с хеша, съхранен от последната успешна синхронизация. Само редовете с променен хеш изискват каквото и да е действие.
При типично почасово изпълнение това може да са 200-800 променени продукта от 50 000. Понякога повече при масово ценово обновяване. Рядко обаче пълният каталог.
Идентифицираме и три категории промяна:
- Обновления: продукти, съществуващи в WooCommerce и имащи променени данни в доставчическия канал
- Нови продукти: SKU-та, налични в доставчическия канал, но все още несъществуващи в WooCommerce
- Премахвания: WooCommerce продукти, свързани с този доставчик, но вече неналични в канала
Обработката на 500 промени отнема секунди. Обработката на 50 000 отнема минути и удря базата данни. Стъпката с разликата е това, правещо почасовата синхронизация реализуема.
Слой 3: Прилагане
Промените се прилагат като опашка от малки, дискретни операции — не единичен монолитен процес.
Всяко обновяване на продукт е отделна задача. Използваме Action Scheduler на WordPress (същата библиотека за фонови задачи, използвана от WooCommerce за собствените му асинхронни операции), за да разпределим работата. Вместо да правим всичко в едно PHP заявка, която може да изтече, изпращаме стотици малки задачи, всяка от които прави едно нещо: обновява единичен продукт.
Това има няколко предимства:
Устойчивост. Ако дадена задача се провали — заключване на базата данни, моментно прекъсване — тя автоматично се опитва отново. Останалите 499 задачи са незасегнати. Провалените задачи се регистрират с точната грешка, за да можем да разследваме конкретни продукти при необходимост.
Пространство за дишане на базата данни. Вместо да удряме базата данни с 500 едновременни записа, задачите се обработват последователно с малки пропуски. Базата данни е заета, но не наситена. Реалният потребителски трафик продължава да реагира нормално.
Видимост. Можем да видим точно колко задачи са чакащи, изпълняващи се и завършени. Ако синхронизацията изостане по каквато и да е причина, дълбочината на опашката ни информира незабавно.
Обработване на сложността в данните
Данните на доставчика не пристигат във формат, съответстващ чисто на WooCommerce. Между суровия канал и показваното в магазина стоят няколко слоя за превод.
Картографиране на категории. Доставчикът използва собствена йерархия на категории, несъответстваща на исканото от нас за клиентите. Поддържаме таблица за картографиране, превеждаща пътеките на категории на доставчика в категории на магазина. Когато в канала се появи нова категория на доставчика, тя е маркирана за преглед вместо безшумно да се създава погрешно категоризиран продукт.
Ценови правила. Mr. Banny не продава на себестойност на доставчика. Правилата за надценка варират по категория, по тип продукт и понякога по конкретни продукти, нуждаещи се от ръчно ценообразуване. Двигателят за синхронизация прилага тези правила по време на фазата на прилагане, трансформирайки цената на едро в цена на дребно съгласно конфигурируем набор от правила. Когато наборът от правила се промени, можем да задействаме преоценяване на съответните продукти без да чакаме промяна в данните на доставчика.
Вариации на продукти. Много продукти се предлагат в множество конфигурации — различни размери, различни материали, различни цветове. Доставчикът ги представя като отделни артикули с връзка на родителски SKU. Ние ги картографираме към WooCommerce вариабилни продукти с атрибути и вариации. Правилното изграждане на това картографиране е по-досадната част от първоначалната настройка, но е стабилно веднъж установено.
Обработване на изображения. Не реимпортираме продуктови изображения при всяка синхронизация, освен ако URL адресът на изображението в канала не се е променил. Изображенията са най-тежката część от всеки продуктов импорт. Изтеглянето и обработката на продуктово изображение, непроменило се, е чиста загуба. Хешираме URL адресите на изображенията по същия начин, по който хешираме данните за продукта.
Поддържане на бързодействие на магазина по време на синхронизация
Наивна имплементация на всичко по-горе все пак би влошила производителността на магазина по време на прозорците за синхронизация поради собственото поведение на WooCommerce за инвалидиране на кеша.
Всеки път, когато обновите продукт в WooCommerce — дори едно поле — то изчиства кеш записите за този продукт, неговите категории, архива на магазина и свързани заявки. Обновете 500 продукта в бърза последователност и задействате инвалидиране на кеша за значителна фракция от сайта едновременно.
Обработваме това по два начина:
Потискане на излишните изчиствания на кеша. По време на операция за синхронизация деактивираме автоматичните hooks за инвалидиране на кеша на WooCommerce и вместо това поставяме на опашка едно целенасочено изчистване на кеша след завършване на групата. Кешът се изчиства веднъж за група от 500, а не 500 пъти поотделно.
Групиране на опашката. Планираме най-тежките задачи (създаване на нови продукти, обновявания на вариации) в прозореца с най-малко трафик за часа — обикновено първите няколко минути след стартиране на синхронизацията — и разпределяме обновленията за остатъка. Ако реалният трафик скочи по време на синхронизация, скоростта на обработка на задачите автоматично намалява въз основа на натоварването на сървъра.
Резултатът е, че посетителят, попаднал на страница с категории по време на активна синхронизация, не забелязва нищо различно. Синхронизацията се случва, но се случва на заден план, учтиво.
Какво наблюдаваме
Толкова автоматизирана система остава надеждна само с правилна видимост. Следим:
Степен на завършване на синхронизацията. Завърши ли последното изпълнение на синхронизацията? Колко продукта са обработени? Колко са се провалили? Предупреждаваме, ако степента на провал надвиши прага или ако синхронизацията не е завършила в разумен период.
Аномалии в данните. Ако изпълнение на синхронизацията ще засегне над 20% от каталога в един проход — цените се променят едновременно, хиляди продукти изчезват — маркираме го за ръчен преглед преди прилагане. Най-вероятното обяснение е грешка в данните на доставчика, а не реална масова промяна.
Ценово отклонение. Регистрираме извадка от ценови изчисления при всяко изпълнение и предупреждаваме, ако приложените цени са извън очакваните диапазони. Това улавя грешки в данните на доставчика и неправилна конфигурация на набора от правила преди клиентите да видят грешни цени.
Дълбочина на опашката. Ако задачите се натрупват по-бързо, отколкото се обработват, нещо не е наред — или сървърът е претоварен, или дадена задача многократно се проваля. Показателят за дълбочина на опашката разкрива това рано.
Какво прави това възможно
Бизнес резултатът е ясен: каталогът на Mr. Banny отразява реалността в рамките на час от всяка промяна при доставчика. Когато продукт излезе от наличност, показва се като недостъпен. Когато цените се сменят, цената в магазина се обновява автоматично съгласно правилата за надценка. Когато в склада пристигнат нови продукти, те се появяват в магазина.
Това премахва цяла категория оперативна работа — ръчни обновявания на цени, проверки на наличностите, поддръжка на продукти — и я замества с система, работеща 24 пъти дневно без никой да я докосва.
Инженерната инвестиция беше значителна. Но беше еднократна инвестиция в инфраструктура, работеща надеждно от 2022 г., обработвайки милиони обновявания на продукти без ръчна намеса.
По-широкият урок
Всяка сериозна e-commerce интеграция накрая се сблъсква с едни и същи проблеми: мащаб, надеждност и пропастта между това, което даден плъгин може да направи, и това, което реално се нуждае от бизнеса ви. Готовите решения са проектирани за общия случай. Когато случаят ви не е общ, имате нужда от нещо изградено за специфичните ви изисквания.
Моделите в тази архитектура — делта синхронизация, поставяне на фонови задачи в опашка, staged прилагане, видимост — надхвърлят WooCommerce. Те са същите модели, използвани във всеки data pipeline, трябващ да бъде едновременно бърз и надежден.
Ако се занимавате с интеграции на каталози, синхронизация на складове или какъвто и да е външен поток от данни, от който магазинът ви зависи, въпросът не е дали да изградите нещо персонализирано. Той е дали бизнесът оправдава инженерната инвестиция. За Mr. Banny очевидно оправдава. За повечето магазини с реален обем и зависимост от доставчик — обикновено оправдава.
