Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS
📢
Канал в Telegram @stendap_sogodni
🦣
@stendap_sogodni@shevtsov.me в Федиверсі
29.06.2023
Запуск локальних скриптів на ECS за допомогою ngrok
В продовження теми з запуском скриптів на ECS, сьогодні винайшов ще більш зручний спосіб. Задача була схожа: зробити бенчмарк, який можливо запустити тільки з середовища ECS. Проблема така сама: на ECS можна запускати тільки готові контейнери Docker. Бенчмарк потребує послідовного налагодження та експериментування. Якщо підходити до цього нормальним шляхом — тобто комітити код, запускати скрипт деплою та очікувати, доки GitHub Actions та AWS CodeDeploy зроблять своє діло — то власне запустити скрипт вдасться раз хвилин в десять. Всякий фокус втрачається.
Тепер в мене є кращий спосіб: скрипт завантажується в контейнер ECS з локального компʼютера. Ніякої попередньої підготовки сервісу для цього не потрібно.
-
На своїй машині запускаємо HTTP сервер з теки:
python -m http.server 7777. Цю команду взагалі варто запамʼятати, бо це найпростіший спосіб роздати файли за HTTP. -
В іншому терміналі запускаємо ngrok:
ngrok http 7777. Таким чином отримуємо доступ до нашого сервісу з інтернету. Ngrok теж треба знати, зазвичай він використовується для отримання тестових вебхуків на локальний додаток. Або ж можна подивитись свій вебдодаток з телефону, наприклад. -
Тепер я можу запускати свіжий скрипт на ECS, замінив команду запуску одним рядком
wget -O benchmark https://ab-cd-ef.ngrok-free.app/benchmark && chmod +x benchmark && ./benchmark. Для цього у нас є утиліта ecs_run. -
Коли закінчив роботу, просто зупиняю сервер та ngrok та жодного “хвосту” в публічному доступі не залишається.
Найкраще це працює з Go, оскільки там все компілюється в єдиний файл, та не треба окремо завантажувати залежності. Проте й в інтерпретованих мовах залежності змінюються не так часто, тому підхід працює.
28.06.2023
Кілька порад з мого повсякденного Git
-
Rebase - чудова команда, бо дозволяє відокремити збереження коду (коміт) від створення документації (підпису до коміту). А саме: оскільки всі зміни можна будь-коли відребейзати, розділити по логічних комітах, та красиво підписати, то попередні коміти можна робити будь-коли — наприклад, перед кожною ризиковою зміною. А не чекати, поки набереться набір змін, вартий коміту. А ще, коли PR виявиться несподівано довгим, або міститиме побічні зміни, можна спокійно їх відрізати, навіть якщо ми цього не планували. Взагалі, поки коміт не покинув твоєї машини, з ним можна робити все що завгодно.
-
Blame - одна з найважливіших функцій Git, бо робить корисним все ведення історії змін. Перша функція Git - поєднання змін від різних людей. Як людина, яка встигла покористуватись SourceSafe, скажу, що ця можливість змінила життя. Але друга функція - це відстеження історії змін. Та з нею можна роздивлятись будь-який баг як не просто комбінацію обставин, але і як подію в історії проєкту. Завдяки команді
git blameможна знайти, де ж баг виник, та які зміни його супроводжували. Часто виявляється, що, наприклад, автор не володів всім контекстом, тоді легше зрозуміти, що треба виправити. Я взагалі постійно дивлюся на вік коду, який редагую, тому в мене blame зʼявляться біля кожного рядка редактора. -
Посилання на Pull Request є в коментарі до кожного merge commit, який робить Гітхаб. Тому я не бачу багато сенсу у вкладанні коду задачі на назву гілки — завжди можна знайти відповідний пул-реквест, та в мене цим часто закінчується пошук причини помилки через
git blame.
27.06.2023
Генерація тестових даних зі справжніх
Почну ось з чого: нагенерувати дані, що виглядають, як справжній результат роботи проєкту — за моїм досвідом — в загальному нереально. А це буває потрібно — може, щоб мати гарні дані для стейджингу; або щоб правильно навантажити системний стрес-тест.
Просто створити записи з синтетичними даними відносно нескладно; для цього є бібліотеки на Ruby чи JavaScript, чи Go. Але це вже на рівні одного обʼєкта може викликати нереальні комбінації даних, а з групами обʼєктів взагалі виникає стільки різних нюансів, що продумати їх вручну стає неможливо. (Скільки коментарів має блог-пост, в середньому? А до скількох коментарів мають бути відповіді? А якщо блог-пост не опублікований? І так далі.) Такі дані підійдуть для автотестів, де відомо, що очікувати, але не допоможуть оцінити роботу продукту до потрапляння в продакшн.
Є інший підхід — взяти дані з продакшна. Там вони за означенням “справжні”. Проте на продакшні містяться дані користувачів, які ми абсолютно не можемо поширювати на стейджинг та інші незахищені середовища. Тоді нам залишається змінити дані з продакшна таким чином, щоб вони втратили привʼязку до користувачів, але зберегли свою топологію, тобто відношення та статистичні властивості.
Я знайшов такий спосіб: використати ті самі бібліотеки фальшивих даних, але передавати їм зерно, обчислене з оригінального значення. З однаковим зерном будь-яка випадкова функція матиме однакове значення, тобто ми будемо впевнені, що структура даних залишається, без того, щоб будувати словник для кожного наявного поля. Де взяти зерно? Пропоную обчислити простий хеш, наприклад, MD5 або SHA1 (простий — бо швидкий!), взяти від нього перші 8 байтів та зліпити з них int64. Далі можна генерувати по зерну хоч імʼя, хоч імейл, хоч ціле оповідання. Вони будуть як правдоподібні (завдяки відповідній бібліотечній функції), так і зберігатимуть статистичні властивості.
Можна навіть зробити копію бази, де кожне поле замінене на своє зерно, а потім використати цю копію як “зерно” для генерації, скажімо, великого масиву даних для стрес-тесту.
(До речі, це може бути хороша задача для нейронної мережі, якщо придумати що робити з приватною інформацією, щоб вона не могла вилізти назовні.)
26.06.2023
Зони відповідальності
В продовження вчорашньої теми, про яку довелося багато сьогодні думати, додам про модель зон відповідальності. В такому вигляді, як я їх використовую, придумав їх сам, хоча звісно, ідея не нова.
Що таке зона відповідальності? Це частинка життя, в середині якої немає конфлікту інтересів. Тобто справи однієї зони рухаються до більш-менш однієї цілі. Та, якщо задачі та цілі є тимчасовими, то зони залишаються, доки не зміняться обставини — фактично, загальний набір зон існує все життя. Тож склавши перелік зон один раз, його вистачить надовго.
Зони відповідальності охоплюють все, на що в житті треба звернути увагу — робота, дім, сімʼя, друзі, здоровʼя і так далі. Але такі макрокатегорії ще розділяються. Наприклад, в роботі окрім зони основної посади може бути зона для гільдії або інших обовʼязків. В сімʼї — зони для найближчої сімʼї, розширеної, батьків та дітей. Окремі зони можуть бути для проєктів, різних хобі. В мене виходить близько 20 зон.
Що це дає:
-
Здатність зробити систематичний огляд поточного стану життя. Я люблю оцінювати кожну зону від 1 до 5 балів за шкалою скільки я б хотів тут поміняти?. Або, може, наскільки все добре, бо 5 - це все чудово, а 1 - це значить, що пора кидати все та виправляти цю зону. Шкала відносна, бо уявлення про потрібний стан з часом змінюються.
-
Спосіб справедливої пріоритизації. Якщо базувати пріоритизацію тільки на важливості окремого проєкту, то можна легко забути про існування інших зон. Наприклад, класична проблема work-life balance. Наявність зон (та їх оцінок) дозволяє більш свідомо обирати, за що братися.
25.06.2023
Самоорганізація з блокнотом, раунд 2
Настав час спробувати систему самоорганізації в блокноті, в наступній ітерації. Головна ціль — це впоратись з ростом кількості задач. В цілому, оригінальна система зберігається, змінюється тільки алгоритм підтримки списку задач.
Система складається приблизно з таких компонент:
-
Збір нотаток в будь-який час; не в блокноті, а електронно, в Drafts. Це я робити й не припиняв, бо звичка засіла міцно. Але є проблема: нотатки самі себе не зроблять. Натомість вони поступово накопичуються та застарівають.
-
Регулярна (щоденна) обробка нотаток та інших вхідних зон — пошти, оповіщень, повідомлень. Без цього я за лічені тижні закопуюсь в інформаційне сміття. От тільки “обробка” має на увазі складання списку задач. Задачі хочуть бути там, де про них не забудуть.
-
Раніше все, що можна “зробити” з вхідних нотаток, потрапляло безпосередньо в поточний список задач, де й накопичувалось безконтрольно (бо вхідний обсяг залежить не від мене.) А тепер, потраплятиме в окремий список “наступних” задач.
-
В поточний список йде тільки те, що вже активно робиться. Або те, що необхідно зробити найближчим часом (є домовленість або термін.) Тут є ризик, що щось так і залишиться в “наступних” задачах, поки не застаріє. Втім, правда в тому, що частина задач завжди відмирає. Мета окремого списку — забезпечити виконання того, що свідомо обране як найважливіше.
-
Коли звільняється місце в поточних справах — беру щось нове. До речі, це дає шанс зрівняти шанси вхідних задач та запланованих. Бо за старою схемою, заплановані задачі програвали вхідним у доступності — перші треба додавати свідомо, останні підсипаються постійно та безупинно.
24.06.2023
Список проєктів та майбутнього в GTD
Останнім часом багато міркую на тему того, як втримати систему самоорганізації від неконтрольованого росту. Хочу поділитися принаймні однією причиною.
Як в мене зʼявляється величезний список задач? Я користуюся алгоритмом GTD - його я запамʼятав багато років тому та так чи інакше він формує моє мислення про задачі. В цьому алгоритмі є ключове питання — чи можна щось зробити з даним предметом? Я сприймав це як — чи не має обʼєктивних перешкод, щоб його робити. Ну, наприклад, я не можу зараз поїхати в турне по Європі. Це йде в список “на майбутнє” - зрозуміло. Але більшість моїх ідей та бажань готові до роботи вже зараз. Вони й поповнювали список активних проєктів.
Здавалося б, нічого поганого в цьому немає, більше ідей — більше можливостей. Але такий великий список неодмінно заглушує ті справи, які вимагають уваги. Це вже розпочаті проєкти та ті, що мають близький термін. Результатом є те, що ти кидаєш такий список та починаєш займатись тим, що чіпляє увагу. В наслідку, щось робиться, щось забувається, та залишається неприємне відчуття нескерованості.
Так от, зробив висновок, що в список проєктів має потрапляти тільки те, що я вже роблю, або маю намір почати сьогодні. Все інше — в “майбутнє”. Та до того ж починати новий проєкт тільки тоді, коли закінчуєш щось старе. Тобто направляти всі зусилля на закінчення початого (принаймні поетапно.) А коли звільняється місце — обирати щось з “майбутнього”.
Мені здається, що це більш правильна інтерпретація GTD, бо вона виправдовує існування “проєкту” як зафіксованої точки, в яку ти рухаєшся. Якщо все “дієздатне” потрапляє в проєкти, та немає різниці, почати новий проєкт або закінчувати старий, то можна обійтися й простим списком задач.
23.06.2023
Повідомлення про відключення AWS, або хто наглядає наглядачів?
Нещодавно в AWS була чергове відключення. На цей раз зачепило й сервіс AWS Lambda, через що в нас відвалилися система моніторингу, та ми були до деякого ступеня сліпі до того, що взагалі відбувається.
Насправді всі сервіси, що не потребують Lambda, були в порядку. Але, наприклад, якщо Lambda використовується для перевірки здоровʼя, то без них можна опинитись в стані, коли ти не можеш запускати або перезапускати сервіси, або ще гірше — вони почнуть зупинятися сами (хоча такої архітектури, де невідомий стан перевірки призводить до перезапуску, краще уникати.)
Можна сказати — при такого масштабу ситуації користувачі самі здогадаються, що відбувається, тому оскільки вона вийшла з-під нашого контролю, то робити нічого не потрібно. Але все ж принаймні варто помітити таку ситуацію та оголосити про неї раніше, ніж користувачі почнуть писати в підтримку.
Для початку, варто налагодити моніторинг, який знаходиться “на відстані” від головного додатка. Це може бути сервіс healthchecks.io. Або моніторинг в іншому регіоні AWS (бо відразу два регіони рідко відключаться.) Або, ще краще, моніторинг з іншого хмарного провайдера (Google або Azure.)
Багато робити не обовʼязково, аби була базова перевірка. Ось ідея на пʼять хвилин: налаштувати Google Alert на запит aws outage site:news.ycombinator.com.
22.06.2023
Tab9
Я, взагалі кажучи, не дуже зацікавлений в використанні сучасних генераторів коду за допомогою нейронних мереж на кшталт Github Copilot. В мене нечасто зустрічаються задачі, яки вимагають створення однотипного коду (якщо це не кодогенерація.)
Але TabNine - помічник зі “штучним інтелектом”, який я використовую ще з 2018 року, практично завжди, та рекомендую кожному. Головна різниця, як на мене — робота TabNine в створенні коротких доповнень, в межах одного твердження. На практиці це виглядає як звичайне доповнення коду в IDE - наприклад, властивостей обʼєкта — але для більш різноманітних сценаріїв та з більшим змістом.
TabNine вчиться на коді проєкту та робить підказки, що використовують його стиль коду та місцеві ідіоми. Наприклад, якщо функції в модулі, або атрибути в класах, називаються за визначеним шаблоном, то він підказуватиме саме такий шаблон. Таким чином, підказки зазвичай містять те, що я й хотів писати, та робота спрощується — без того, щоб генерувати великі шматки коду, які потім потрібно вичитувати та перевіряти.
Також дуже важливо для мене, що TabNine працює локально. Головним чином, тому, що я не переймаюсь про безпеку кода — свого та клієнтів. Хоча це й ненажерлива на оперативну пам’ять функція — кожний відкритий проєкт споживає близько 500 Мб, а проєктів в мене відкрито від 4 та більше. (Локальний режим треба увімкнути окремо, та він не підтримує “просунутих”, тобто довгих, доповнень.)
21.06.2023
Версіювання кешу
Фольклор програмування каже, що складних проблем всього дві — іменування та очищення кешу. Сьогодні натрапив на не найбільш очевидну ситуацію, коли кеш пора очистити.
Є сервіс. Він повертає конфігурацію. Конфігурація потрібна часто, а отримується повільно. Тому вона кешується. В цьому випадку кеш дуже абстрагований та просто зберігає все, що повертає сервіс. Тому для споживача чи є кеш, чи немає — непомітно.
Кеш цей чиститься за терміном придатності — тобто, взагалі коду, який його явно чистить, немає.
Проблема зʼявилась, коли я додав до об’єкта конфігурації ще одне поле. Тести пройшли, звісно — як юніт-тести, так й інтеграційні. А на стейджингу виявилось, що поле порожнє та повʼязана логіка падає. Це трапилось тому, що в кеші було збережена конфігурація, збережена минулою версією коду.
Для таких ситуацій є одне пряме рішення — ключ кешу маємо поміняти так, щоб новий код не міг знайти старий кеш. Класично, в ключі має міститься версія: config:v1:, config:v2: і так далі. Так старі значення будуть видалені за терміном. Цей підхід залишає роботу з кешем в одному шарі, та не розмазує обробку неочікуваних ситуацій по програмі.
Однак мені більш цікаво, як не пропустити таку помилку. Бо коли ти працюєш над сервісом, то кеш знаходиться поза зоною уваги. Найкраще, що придумав — то присипати код коментарями (а саме, біля структури з конфігурацією додати коментар “не забудь оновити версію кешу, коли редагуєш цю структуру”).
20.06.2023
Soulver - програма для розрахунків "на папері"
Soulver - це та програма, яка тобі потрібна, але ти про це не знаєш. Вона робить обчислення на конкретному рівні складності: коли за один крок в калькуляторі всього не зробиш, а писати скрипт або робити таблицю ще незрозуміло, як, або надто складно.
Натомість в Soulver можна писати формули приблизно так, як це робиться на папері: в більш розслабленому синтаксисі, поруч з іншим текстом для розʼяснень. Це як блокнот, який миттєво обчислює все, що в нього напишеш.
От, наприклад: я робив скрипт, який міряє кількість записів та за який час він встиг їх відправити. А потім знадобилось підрахувати швидкість у записах на секунду. А може, на годину? Скрипт вже відпрацював, тож вкласти таке просте обчислення всередину я вже не можу. Замість того, щоб вручну переводити години/хвилини/секунди, в Soulver можна просто скопіювати результат роботи скрипту, мінімально відредагувати та отримати результат.
Мені подобається, що як й на папері, в Soulver зберігається весь хід обчислень та результати кожного кроку. Знайти помилку так значно простіше, ніж в коді. Та й експериментувати простіше.
Для розробки прототипів, планування ремонту чи бюджету поїздки - Soulver це те, що треба.
Ще є Numi, яка схожа, але за моїм досвідом функцій в неї менше.
PS Пост короткий, бо я встановив гру Cityscapes з Apple Arcade та підвис в неї на весь вечір. Таке враження, що гра була збалансована на типові сучасні обмеження “чекай або плати”. Але в Apple Arcade такого ніколи не буває — навіть у тих ігор, що раніше були платними, просто прибирають всі обмеження. Тому події у грі ніколи не припиняються, вона хапає і не відпускає. Проте хороша гра, простий такий будівельник міста, шкода тільки що інтерфейс розроблений очевидно для iPad.

