Оптовая платформа цифровых товаров

Multi-source routing 2026: маршрутизация заказов между поставщиками

Production-алгоритмы multi-source routing: latency-weighted, stock-aware, cost-optimised и failover для B2B-фулфилмента.

Multi-source routing 2026: маршрутизация заказов между поставщиками

Production B2B-фулфилмент цифровых товаров не зависит от одного поставщика. Эксклюзивный supplier — это single point of failure: один даунтайм, и все ваши заказы fail. Правильный архитектурный паттерн — multi-source routing с автоматическим выбором лучшего варианта на каждый запрос.

1. Latency-weighted routing

Самый простой вариант — выбирать поставщика с минимальной p95 delivery latency. Хранить historical-метрики в Redis sliding window:

type SupplierStats = { p95Ms: number; failureRate: number; stock: number };

async function pickSupplier(productId: string): Promise<string> {
  const candidates = await getSuppliersForProduct(productId);
  const stats = await Promise.all(
    candidates.map(s => redis.hgetall(`sup:${s.id}:stats`))
  );
  const scored = candidates.map((s, i) => ({
    id: s.id,
    score: 1 / (parseFloat(stats[i].p95Ms) + 1),
  }));
  return scored.sort((a, b) => b.score - a.score)[0].id;
}

Этого достаточно для 80% сценариев. Latency-метрики обновляются каждые 30 секунд из реальных тиймингов опроса статуса.

2. Stock-aware routing

Если у поставщика inventory низкий — лучше не использовать его как primary, даже если latency хорошая. Stock buffer защищает от race condition «4 одновременных заказа на 3 кода».

function isViableSupplier(s: SupplierStats, qty: number): boolean {
  const buffer = Math.max(50, qty * 3); // 3x safety margin
  return s.stock >= buffer && s.failureRate < 0.05;
}

Для FoxReload наличие товара отражается в каталоге — запрашивайте GET /api/products/{id_or_slug} для проверки актуальной доступности.

3. Cost-optimised routing

Если SLA позволяет (например, fulfilment до 5 минут — норма для B2B), оптимизируйте по wholesale-cost. Формула:

score = (1 / wholesale_cost) * sla_multiplier
where sla_multiplier = 1 if p95 < target else 0

Это даёт жёсткий SLA-гарантия + минимальный cost. На больших объёмах (>10k заказов/день) экономия 1.5–3% к marginal cost.

4. Интеграция с FoxReload: создание и опрос заказа

Создание заказа через FoxReload:

async function placeOrderOnFoxReload(
  itemId: string,
  quantity: number,
  note?: Record<string, string>
): Promise<Order> {
  const resp = await fetch('https://public-api.foxreload.com/api/orders', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.FOXRELOAD_KEY!,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      items: [{ itemId, quantity, ...(note && { note }) }],
      isMock: false,
    }),
  });
  if (!resp.ok) throw new Error(`FoxReload error: ${resp.status}`);
  const order = await resp.json();

  // FoxReload не поддерживает вебхуки — опрашиваем статус
  return pollOrderStatus(order.id);
}

async function pollOrderStatus(orderId: string): Promise<Order> {
  for (let i = 0; i < 20; i++) {
    await sleep(Math.min(1000 * Math.pow(2, i), 15000));
    const r = await fetch(`https://public-api.foxreload.com/api/orders/${orderId}`, {
      headers: { 'X-API-Key': process.env.FOXRELOAD_KEY! },
    });
    const o = await r.json();
    if (['completed', 'cancelled', 'failed'].includes(o.status)) return o;
  }
  throw new Error('poll timeout');
}

5. Failover и circuit breaker

Health-check pattern:

Сигнал Threshold Action
5xx rate за 5 мин >5% Mark DEGRADED
Timeout rate >2% Mark DEGRADED
Heartbeat fail 3 × подряд Mark DOWN
Recovery 5 × успешных Mark HEALTHY

Circuit breaker pattern (Polly/resilience4j-style):

import CircuitBreaker from 'opossum';

const breaker = new CircuitBreaker(placeOrderOnFoxReload, {
  timeout: 8000,
  errorThresholdPercentage: 50,
  resetTimeout: 120000, // 2 min
});

breaker.fallback(() => fallbackSupplier());

При open-state 100% traffic уходит на fallback — 2 минуты cooldown, потом half-open canary check, потом recovery.

CTA

FoxReload предоставляет доступ к широкому ассортименту цифровых товаров через единый API. Получите доступ и переведите фулфилмент на надёжную основу.

Часто задаваемые вопросы

Что произойдёт, если основной поставщик down?
Health-check каждые 10 секунд (heartbeat + sample-order). Если 3 fails подряд — supplier помечается DEGRADED, traffic переключается на secondary. Recovery — после 5 successful checks подряд.
Как multi-source влияет на end-customer latency?
В среднем добавляет 80–120ms на routing-decision (внутренний lookup), но снижает p99 delivery на 40–60% за счёт failover. Без multi-source p99 может достигать 90s; с multi-source — снижается до 38s.
Нужно ли по-разному обрабатывать статусы у разных поставщиков?
Да. Каждый поставщик может иметь свою модель статусов. Для FoxReload терминальные состояния: completed, cancelled, failed. Нормализуйте статусы поставщиков в единый внутренний enum в вашей системе.
Как обрабатывать partial fulfilment при multi-source?
FoxReload заказ содержит items[] — каждая позиция может иметь свой статус. Проверяйте items[].error на уровне позиции при статусе failed. Для частичного выполнения обрабатывайте каждую позицию независимо.
Получить доступ к FoxReload API

Похожие статьи