Продукт лишається одним. Обіцянка кожному клієнту була іншою: його записи лишаються його. Лекція про схему бази тут не потрібна. Потрібні місця, де межа зазвичай рветься, питання перед наступним звітом або інтеграцією, і перевірка двома входами.
Швидкість — сусідня історія. Звіт, який відкривається швидше і все одно показує чужу компанію, кращим не став. Нижче лише межа. Замінювати продукт я не пропоную.
1. Звіт — місце, де плутанину нарешті бачать
Клієнт не дивиться на схему. Він бачить своє ім’я в кутку і чужі цифри в таблиці. Зазвичай це звіт: дзвінки за місяць, неоплачені рахунки, порівняння філій. Його збирали, коли компанія була одна, або збирав хтось, хто бачить усіх і не помітив, що фільтр необов’язковий.
Слабке місце майже завжди список компаній. Він пам’ятає останню. У ньому є «всі», до якого дотягується клієнт. Або в листі вже зашитий чужий id. Екран перевіряли під адміністратором. Адміністратору якраз належить бачити всіх. Клієнту ні. Вхід адміністратора обіцянку не перевіряє.
Візьміть два справжні клієнтські входи або два тестові, яким не можна бачити одне одного. Відкрийте той самий звіт під кожним і запишіть рядки. Крутилка вас не цікавить. Цікавить прізвище, філія або сума, які належать іншому входу.
Якщо звіт ще й довго вантажиться, секунди засічіть потім, на тому самому екрані. Як розбирати очікування, не міняючи продукт: звіти, через які люди чекають. Не дайте очікуванню сховати чужі рядки і не розширюйте запит «раз уже відкрили», поки межа не тримається.
2. Нічний файл і лист живуть окремо від екрана
Екран може бути чистим, а задача, яка вночі збирає файл або шле зведення, ні. Її писали як «відкрий базу і пройди по рядках». Коли з’явився другий клієнт, задача й далі відкривала ту базу, яку їй дали, або всі рядки поспіль, бо клієнта так і не поклали в повідомлення, з якого вона стартує.
На одній CRM у кожної філії була своя база. Міграції й індекси збирали під цей розріз, а не приклеювали потім «для швидкості». У фонової роботи було друге правило: повторний запуск не шле другого листа і не пише другої оцінки. І воркер відмовлявся від з’єднання, яке не збігалося з філією в повідомленні.
Задача, яка відкриває «ту саму» базу і вірить тексту, спокійно запише рядки однієї філії як рядки іншої. Черга різниці не бачить. Клієнта називає повідомлення, а воркер мусить відкинути з’єднання, яке з цим іменем не сходиться.
Спитати це можна, не читаючи воркер. Яка задача шле пошту або збирає файл? Якого клієнта цьому запуску можна торкатися? Що буде, якщо вона стартує двічі? Якщо відповідь «бере основну базу», уточніть, що таке «основна», коли клієнтів уже кілька. Як влаштований безпечний повтор і чому другий процес не лікує плутане повідомлення: коли робота йде з вебзапиту.
3. Хто має право бачити всіх
Хтось мусить бачити впоперек клієнтів: ви, підтримка, іноді агенція, яка впроваджує продукт. Сам доступ не баг. Баг — обліковий запис, який перемикає компанії, а екран не каже, чиї дані відкриті. Або перемикання, яке виявилося закладкою, і її переслали. Або спільний пароль, залишений у чаті. Рядки «витекли» руками людини, яка думала, що дивиться свою компанію.
Поточна компанія має бути написана на екрані. Перемикання — окрема дія, після якої лишається слід. Один пароль на всіх, хто колись був на дзвінку, не годиться.
Коли агенція віддає продукт новому розробнику, цей обліковий запис — сюрприз, який має лежати в першій записці, а не виринати на живій системі. Пакет такої передачі: що агенція готує до відкриття чужого Laravel.
4. Пошук, нова інтеграція, нова колонка
Пошук плутає компанії тихіше за звіт. Поле дивиться по всіх, бо індекс побудували на спільній таблиці і клієнта в нього не поклали. Немає індексу — пошук здається зламаним, бо довго вантажиться. Немає межі — пошук здається дивним, бо потрібне прізвище знаходиться в чужої компанії. Це різні поломки. Пришвидшити пошук, не закривши межу, означає привозити чужі рядки раніше.
На тій CRM індекси були частиною розрізу по базах філій, а не спробою розігнати спільну купу.
Інтеграція рве межу ще тихіше. Телефонія, повідомлення, бухгалтерія, оцінка дзвінка: зовнішня система надсилає ідентифікатор, ваш продукт пише рядок. Якщо воркер вірить ідентифікатору і пише в базу, яка вже була відкрита, дзвінок сідає не в ту філію. На тому продукті інтеграції жили за тим самим правилом, що звіти. Повідомлення називало філію, воркер брав її базу. Бухгалтерії й листуванню не робили винятку на тій підставі, що це «просто синхронізація».
Перед наступним звітом, вивантаженням, полем пошуку або інтеграцією допишіть у запит один рядок: перевірено двома клієнтами, які не повинні бачити одне одного. Якщо єдине місце для перевірки — продакшен, не ганяйте її по живих клієнтах як першу спробу. Копія, хай навіть чорнова, — місце, де кривому запиту дозволено показати чужі рядки. Лізти в живий продукт «подивитися, чи тримається фільтр» — та сама нічна правка без свідка, про яку йдеться в нотатці чому це погано з’ясовувати на живому сайті.
Своя база на філію — робоча форма, якщо міграції й індекси зібрані навколо розрізу. Спільна база на всіх теж працює, якщо кожен шлях мусить назвати клієнта і ви це довели двома входами. Ламається шлях, який забув. Чужий кресленик не доводить, що у вас безпечно, і не привід переписувати продукт до того, як ви двічі відкрили звіт.
5. План на цей продукт, не на новий
Сьогодні: два входи на звіті, якому люди вже вірять, і на одному вивантаженні або листі. Запишіть, що побачив кожен. Далі: список задач і інтеграцій, у кожної — клієнт, якого запуску можна торкатися, і що дозволено повтору. Потім: кожен новий екран починається з рядка про двох клієнтів.
Заміна продукту — розмова на потім, і лише якщо поточний цей рядок утримати не може. Частіше може. Його випустили без перевірки.
Коли двох входів уже мало
Відкрити два входи і побачити чуже прізвище в таблиці можна без розробника. Кличте, коли другого входу не дістати, коли база в задачі — знизування плечима, коли інтеграція вже написала рядки і незрозуміло, чиї вони, або коли єдина пропозиція — пришвидшити запит, у якому клієнта досі немає.
На продукті, в якого вже є клієнти, я починаю з межі, потім зі звіту або задачі. Послуги — SaaS і backend, звіти навколо них і інтеграції, які пишуть назад. Роботи тримають результат біля операції, зокрема CRM, де у філії була своя база. Якщо потрібен другий погляд, напишіть у LinkedIn назву звіту і що показали два входи. Вивантаження клієнтських рядків не надсилайте.