net·devs
← Всі статті
File insight
3 хв читанняАвтор: Kyrylo Osadchuklogisticsmobile

Ваш застосунок для водіїв має працювати в клітці Фарадея

Логістичний застосунок, що передбачає з'єднання, зламається у виробництві приблизно на третій день. Будівництво офлайн-first — це не преміум-інженерія, а єдиний вид, що виходить у реліз.

Найкорисніша вправа, яку ми проводимо для нового логістичного клієнта — це тест ліфта. Беремо телефон водія і заходимо у вантажний ліфт на вантажному дворі. Закриваємо двері. Дивимося на застосунок.

Якщо застосунок перетворюється на спіннер, зависає, втрачає місце користувача або — найпоширеніша помилка — мовчки губить скан, який водій щойно виконав, застосунок не готовий до виробництва. Водії проводять значну частину дня в сталевих коробках, бетонних будівлях, сільських мертвих зонах і тунелях. Зв'язок — це не властивість, яку вони мають. Це властивість, яку вони іноді мають.

Таке реальне обмеження. Будувати для нього — це не преміум-інженерія, а єдиний вид, що виходить у реліз.

Три режими збою, які вражають команди щоразу

Після достатньої кількості логістичних проектів три режими збою з'являються знову й знову.

Оптимістичний запис, якого не було. Водій сканує пакет. Застосунок показує "відскановано". Сервер через мережевий збій запис не отримав. Водій вважає, що пакет у системі; система — ні. Пакет потрапляє на наступну зупинку, і ніхто не знає, що з ним робити. Першопричина: застосунок показав успіх на основі локальної дії без підтвердження від сервера і без способу для водія дізнатися про різницю.

Логін, якому потрібна мережа. Водій з'являється на початку зміни, і телефон втратив сесію. Екран входу мусить звернутися до auth-сервера. Водій стоїть на парковці з двома поділками покриття, які падають до нуля, щойно вантажівка рушає. Зміна не може почастися. Кожна хвилина — оплачуваний час, і телефон диспетчера вже дзвонить.

Черга "синхронізую пізніше", яка губить дані. Багато команд будують офлайн-підтримку, ставлячи дії в чергу локально і синхронізуючи при відновленні мережі. Це працює, поки черга не переростає обсяг пристрою, або користувач закриває застосунок і черга губиться, або код синхронізації має баг і мовчки скидає елементи. Водій робить роботу правильно. Дані не надходять. Водія звинувачують.

Що насправді вимагає офлайн-first

Офлайн-first — це не функція, яку додають. Це властивість архітектури, і або застосунок побудований навколо неї з першого дня, або ні.

Форма, яка працює:

Локальне сховище є джерелом правди для сесії. Коли водій сканує пакет, скан записується в надійне локальне сховище негайно, і UI читає з нього. Серверна синхронізація — окремий процес, що запускається, коли може. UI не чекає сервера; він показує локальний стан, який і є реальним станом, що водій бачить.

Кожна дія має ID, згенерований на стороні клієнта. UUID-и, згенеровані на пристрої до виконання дії. Це означає, що ту ж дію можна безпечно повторювати нескінченно без створення дублікатів на сервері, і дія існує в локальному сховищі зі стабільним ідентифікатором навіть до того, як сервер її коли-небудь побачить.

Синхронізація видима користувачеві, а не прихована. Маленький індикатор: "12 дій очікують, остання синхронізація 4 хвилини тому." Водії вважають це заспокійливим. Вони хочуть знати, чи зафіксована їхня робота. Приховування стану синхронізації заради "чистоти UX" — це те, що призводить до сценарію "відсканував, але насправді ні."

Токени автентифікації мають тривалий офлайн-термін. Ввійшли один раз — отримали токен, що витримує кілька діб офлайн. Оновлюйте токен у фоні, коли мережа є. Збій мережі при оновленні токена — нонсенс; лише реально прострочений без оновлення токен повинен примушувати до повторного входу. Ця одна зміна усуває найпоширенішу помилку початку робочого дня.

Що це змінює на серверній стороні

Офлайн-first зазвичай розглядається як клієнтська властивість. Але вона має наслідки й для сервера.

Серверні endpoint-и мають бути ідемпотентними. Клієнт повторюватиме запити. Повтори відбудуться через дні після оригіналу. Оригінал може бути отриманий, а може й ні. Endpoint мусить обробляти "я вже обробив цю дію з цим клієнтським ID" коректно — повертаючи той самий результат, а не створюючи дублікат або відхиляючи запит.

Час на сервері — це не той самий час, що на клієнті. Дія виконана о 9:14 за місцевим часом водія, але сервер фіксує її о 11:47 після повернення водія до зони покриття. Кожен запис потребує обох міток часу. Звіти, що їх плутають, вводитимуть бізнес в оману.

Структура даних має допускати врешті-узгоджені правки. Водій може позначити пакет доставленим, а потім супервайзер може позначити його як повернення — до того, як дія водія синхронізується. Вирішення конфліктів має бути навмисним, а не "перемагає останній запис за випадковістю." Зазвичай правило таке: "дія водія має пріоритет у межах зміни, дія супервайзера — після зміни", але це залежить від бізнесу.

Практичний тест

Якщо ви оцінюєте логістичну платформу — купуєте чи будуєте — спочатку запустіть тест ліфта. Візьміть застосунок, телефон, закрийте двері ліфта, виконайте звичайне завдання. Подивіться, що відбудеться.

Платформи, що проходять цей тест, зазвичай в нормі. Ті, що провалюються — провалюватимуться у виробництві щодня і звинувачуватимуть мережу, коли це станеться.

Хочемо почути ваші думки.

наш CTO Кирило Осадчук відповість протягом 24 годин. Без воронки продажів.