Перейти до основного вмісту
Версія: 2.0

Sticky execution

Sticky execution — це підтримувана оптимізація replay Durable Workflow v2. Worker може зберігати прогрітий локальний кеш workflow після завершення завдання workflow, а підбір завдань може надавати йому перевагу для наступного завдання workflow того самого запуску.

Sticky execution не є засобом забезпечення коректності. Прогрес workflow фіксується лише через стійку історію, а звичайний холодний replay з історії завжди залишається коректним. Код workflow не має покладатися на локальний стан процесу для забезпечення правильності.

Стислий контракт​

Sticky execution надає чотири гарантії:

  • Sticky-кеші належать процесам worker, а не серверу чи базі даних.
  • Sticky-маршрутизація використовує worker_id протоколу worker як ідентичність маршрутизації.
  • Sticky-прив’язка є рекомендаційною та має термін дії. Холодний replay — обов’язковий запасний шлях після промаху кешу, перезапуску worker, drain, розгортання або витіснення.
  • Оператори мають явні параметри й діагностику ввімкнення, TTL, місткості, частки влучань і промахів, примусового холодного replay та тиску на місткість.

Стійкі поля прив’язки — sticky_worker_id та sticky_until у запусках і завданнях workflow. Поля діагностики завдань workflow — sticky_replay_mode та sticky_claimed_at.

Життєвий цикл sticky-кешу​

Sticky-кеш — це локальна структура даних worker із відтвореним станом workflow одного чи кількох запусків. Коли worker із підтримкою sticky завершує завдання workflow, сервер може записати його як sticky-власника запуску до sticky_until. Подальші завдання workflow успадковують цю прив’язку під час створення.

Worker володіє вмістом кешу й політикою витіснення. Він може витісняти кешовані запуски за досягнення місткості, початку drain, перезапуску, зміни збірки, виявлення небезпечного кешованого стану або потреби звільнити пам’ять. Сервер ніколи не вважає вміст кешу стійким станом.

Якщо worker отримує завдання зі sticky-маршрутизацією, але вже не має чинного запису кешу, він мусить виконати холодний replay зі стійкої історії. Оренда завдання залишається єдиною підставою для фіксації прогресу workflow.

Ідентичність маршрутизації​

Ідентичність маршрутизації — це worker_id протоколу worker. Worker обирають sticky-маршрутизацію, реєструючись із увімкненим sticky-кешем і продовжуючи надсилати heartbeat як активні worker черги завдань.

Підбір завдань дотримується таких правил:

  • Перевага надається завданню з активною прив’язкою до worker, який опитує чергу.
  • Завдання без активної прив’язки може отримати будь-який сумісний worker.
  • Завдання з активною прив’язкою до іншого живого sticky-worker утримується для нього до спливу sticky_until або недоступності власника.
  • Завдання зі спливлою прив’язкою, застарілим власником або вимкненим sticky execution можна отримати звичайним способом і відтворити холодним replay.

Sticky-маршрутизація не оминає перевірок сумісності, черги, namespace чи оренди. Вона лише змінює пріоритет готових завдань, зберігаючи звичайний replay як запасний шлях.

Семантика запасного шляху​

Холодний replay є обов’язковим запасним шляхом. Він застосовується, коли:

  • sticky execution вимкнено.
  • worker не зареєстрував підтримку sticky-кешу.
  • завдання не має активних sticky_worker_id та sticky_until.
  • sticky-власник застарів, відсутній, перебуває у drain, перезапущений або замінений під час розгортання.
  • sticky-власник витіснив запуск.
  • worker, який опитує чергу, не є sticky-власником після спливу прив’язки.

Діагностика режиму replay:

  • sticky_hit_expected — sticky-власник отримав завдання до спливу терміну.
  • cold_replay — sticky-прив’язка не застосовувалася.
  • forced_cold_replay — прив’язка існувала, але завдання потребує холодного replay.

forced_cold_replay не означає порушення коректності. Він означає, що sticky execution не забезпечив очікуваного прискорення replay для цього завдання.

Розгортання, drain і заміна worker​

Sticky execution дотримується життєвого циклу worker. Під час drain worker має припинити отримання нових завдань workflow, водночас завершуючи поточні, надсилаючи heartbeat, повідомляючи про помилки або дозволяючи чинним орендам спливти за звичайним контрактом. Коли worker стає застарілим або неактивним, інші сумісні worker можуть отримати його sticky-завдання після спливу прив’язки й виконати холодний replay.

Нові worker не успадковують локальних кешів попередніх процесів. Тому розгортання може збільшити forced_cold_replay, доки нові worker не прогріють власні кеші. Використовуйте унікальні worker_id для кожного процесу worker або перезапуску, щоб діагностика оператора розрізняла старого власника кешу й новий процес.

Сумісність build-id та відбиток визначення workflow і далі визначають, чи може worker виконувати завдання workflow. Sticky execution не дозволяє спрямувати несумісний код до запуску.

Засоби керування оператора​

Sticky execution керується налаштуваннями workflow/runtime та можливостями worker, а не окремими змінними середовища серверного образу. Конфігурація пакета workflow надає прапорець увімкнення й TTL прив’язки:

'workflows' => [
'v2' => [
'sticky_execution' => [
'enabled' => true,
'ttl_seconds' => 300,
],
],
],

Кожен worker повідомляє місткість кешу під час реєстрації та heartbeat. Sticky-маршрутизацію можна вимкнути в налаштуваннях runtime або запускати worker без підтримки sticky-кешу, не змінюючи семантики workflow. Наявні запуски продовжуються через звичайний холодний replay.

Поля протоколу worker​

Worker із підтримкою sticky повідомляють про неї під час реєстрації:

{
"worker_id": "orders-worker-01",
"task_queue": "orders",
"runtime": "python",
"sticky_cache_enabled": true,
"sticky_cache_capacity": 100
}

Worker повідомляють діагностику кешу через heartbeat:

{
"worker_id": "orders-worker-01",
"sticky_cache": {
"enabled": true,
"capacity": 100,
"size": 72,
"hit_count": 940,
"miss_count": 31,
"forced_cold_replay_count": 8,
"eviction_count": 15
}
}

Відповіді опитування завдань workflow містять task.sticky_execution з sticky_worker_id, sticky_until, replay_mode та cache_directive. Worker мають трактувати resume_if_present як дозвіл використати чинний прогрітий кеш і виконувати холодний replay, якщо запис відсутній або нечинний.

Метрики й діагностика​

Метрики оператора містять:

  • sticky_execution.active_sticky_runs
  • sticky_execution.ready_sticky_tasks
  • sticky_execution.leased_sticky_tasks
  • sticky_execution.hit_expected_last_minute
  • sticky_execution.miss_last_minute
  • sticky_execution.forced_cold_replay_last_minute
  • sticky_execution.cold_replay_last_minute
  • sticky_execution.hit_rate_last_minute
  • sticky_execution.miss_rate_last_minute
  • sticky_execution.capacity_pressure_tasks

Окремий сервер також повідомляє в sticky_execution_workers місткість і розмір кешу worker, кількість влучань, промахів, примусових холодних replay, витіснень кешу та worker із тиском на місткість.

Трактуйте діагностику так:

  • Низька частка влучань за здорових worker зазвичай означає надто короткий TTL, часту заміну worker або замалу місткість кешу.
  • Висока частка промахів або примусових холодних replay означає, що коректність збережено, але sticky execution не зменшує вартість replay.
  • Тиск на місткість означає, що worker наближаються до заявленої місткості sticky-кешу або перевищують її й можуть витісняти прогріті запуски.

Код, безпечний щодо replay​

Код workflow має поводитися однаково за sticky-виконання й холодного replay. Рішення workflow мають спиратися на стійку історію: вхідні дані workflow, результати activity, timer, signal, update, побічні ефекти й маркери версій. Проєкції memo та атрибутів пошуку є метаданими оператора. Не обирайте гілки логіки workflow за їхніми змінюваними значеннями.

Для коректності не покладайтеся на змінювані глобальні дані, локальні файли, відкриті сокети, ідентичність об’єктів, випадкові значення, поточний календарний час або інший локальний стан процесу. Sticky execution може випадково зберегти їх для одного завдання, а потім втратити після промаху кешу, перезапуску worker, розгортання або витіснення.

Використовуйте sideEffect(...) для недетермінованих значень, які потрібно записати один раз, а звичайні activity — для зовнішніх побічних ефектів. Контракт replay та стійкої історії наведено в розділі Гарантії виконання та ідемпотентність.