Стендап Сьогодні

Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті

Підписатись на RSS
📢 Канал в Telegram @stendap_sogodni
🦣 @stendap_sogodni@shevtsov.me в Федиверсі

16.07.2023

Ruby у VSCode - станом на 2023

Сьогодні приділив уваги своєму оточенню розробки на Ruby в VS Code. Сприяло цьому те, що після увімкнення доповнення Error Lens помилки Rubocop на одному з маленьких проєктів стали більш очевидними та навіть нестерпними. (Rubocop в мене був увімкнений для всіх проєктів, але налаштований — не для всіх.) Окрім банального створення .rubocop.yml та вимикання деяких непотрібних правил, захотілося також, щоб автоматичне виправлення відбувалось після зберігання файлу.

Дізнався, що канонічне доповнення vscode-ruby офіційно оголошене застарілим. Вони рекомендують перейти на доповнення Ruby LSP. Мотивація в тому, що Ruby LSP являє собою мовний сервер, написаний на самому Ruby, що є більш перспективною архітектурою. Та дійсно, хоч обидва доповнення вміють запускати Rubocop на збереження файлу, Ruby LSP робить це помітно швидше — практично миттєво. От тільки дратує те, що обидва доповнення не дозволяють обрати рівень виправлень, хоча це робиться простою зміною аргументу для Rubocop. Тут обговорення.

Поки з всім цим розбирався, зрозумів, що насправді я хочу Prettier. Тим паче що з Ruby LSP можна виправляти складніші помилки Rubocop через вікно “Quick Fix” (cmd+.) А поки намагався налаштувати prettier-ruby, зрозумів, що це просто обгортка над гемом syntax_tree - причому Ruby LSP вже вміє форматувати саме цим гемом. Так що Ruby LSP вже пропонує найкращий автоформатувальник коду для Ruby. Чи добре він працює, зможу поділитися пізніше.

…Але є нюанс. Та дуже важливий. На поточний момент, Ruby LSP не показує в коді синтаксичні помилки. Звісно, це вкрай незручно. Тому після деяких вагань я повернув також доповнення vscode-ruby, тільки увімкнув в ньому єдину функцію Lint.


15.07.2023

Rails на AWS Lambda - чому ні? або чому так?

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

З технічної сторони різниці небагато. Як Lambda, так і Fargate, а також Fly.io та інші контейнеризовані хостинги використовують технологію віртуалізації Firecracker. Тому Lambda здатна запустити те ж саме, що й звичайний Docker-хостинг. Відмінність цих сервісів не в реалізації, а в рівні абстракції, яку вони пропонують.

Типовий вебдодаток вже є колекцією функцій, які ми викликаємо за протоколом HTTP. Є тільки один нюанс — в додатку не повинно бути власного стану. Проте сучасна парадигма 12-Factor App пропонує це для всіх додатків. Звісно, як я писав, не всі додатки підходять під цю модель — але типовий CRUD-додаток - цілком.

Деякий “стан” все одно буде в додатку. Це завантажений в оперативну памʼять код, підключення до бази даних, кеш. Все це ми втрачаємо з Lambda - наприклад, код доведеться щоразу завантажувати наново. Звісно, якщо запити робляться часто, то Lambda зі своїм станом буде збережена в памʼяті. Але тоді вона мало чим відрізняється від звичайного сервісу — окрім ціни, звісно.

Оскільки вартість Lambda вимірюється в запитах та їх тривалості, а вартість Fargate - в обсягах, можна обчислити, скільки разів можна запустити Lambda, щоб це було вигідно. Година Fargate з 1 CPU + 2 GB = $0.04947. Мільйон запусків Lambda з 2 GB, кожний з яких триває 100 мс (типовий час для вебдодатка) = $3.53. Виходить, 14000 разів на годину. Не так вже й мало! Виходить, на AWS Lambda можна економічно розгортати сервіси з невеликим навантаженням.

З боку розробки, в деяких моментах Lambda додають складнощів (наприклад, їх не так прямо можна запустити локально), але суттєвої різниці немає. Такі бібліотеки, як Lamby дозволяють прямо використати Ruby on Rails на Lambda, або Jets - пропонує схожу на Rails абстракцію контролерів.

Lambda мають версії, та їх підтримує CodeDeploy. Тому обережне розгортування Lambda можливе, як і екстрене повернення на попередню версію — якщо перед Lambda стоїть обгортка, яка обирає активну версію. Підхід ECS мені більше подобається, бо там сервіс знає, яку версію запускати.

Lambda можна відвантажувати у формі архіву, а не тільки образу Docker. Це суттєво спрощує підготовку додатка, якщо середовище дозволяє. А з іншого боку, збірка Docker універсальна, а з архівом треба розбиратись.

Як з Fargate, так і з Lambda, доведеться створити багато різних ресурсів, щоб сервіс почав працювати — ролі, ALB або Gateway, і таке інше. Простіше буде на Fly.io.

До речі, на Fly.io хостинг в 4 рази дешевше, ніж Fargate, тож математика зсувається. Як я писав, Fly.io варто мати у своєму інструментарії для простого запуску сервісів. Але як я також писав, сервіс не завжди потрібний, а невеликий парк функцій буде більш економічним в підтримці та розміщенні.


14.07.2023

Як перетворити прототип на пул-реквести

Мабуть, всім знайомий підхід до розробки Red-Green-Refactor, де функціонал зʼявляється в коді поступово, та після кожної зміни код завжди працює — єдине питання, що саме він вміє зараз. Одна з переваг такого підходу — це зручні, послідовні пачки змін, які легко зрозуміти вашим оглядачам.

Проте в моїй практиці постійно трапляються задачі, які починаються з прототипа. Прототип зазвичай робиться без чіткого плану змін, бо замість плану відбувається ітеративний процес дослідження та доробки коду, без уявлення, що саме за код доведеться писати та де. В результаті, коли все запрацює, виходить добрячий шмат коду, який в один Pull Request вже не влізе. Головним чином, тому, що зрозуміти його за один підхід неможливо. Що я роблю в таких ситуаціях?

В теорії, можна прототип викинути та зробити наново за планом. На практиці, таке трапляється тільки коли прототип за природою відрізняється від остаточного коду (може, написаний іншою мовою.) А в типовому випадку я доробляю та рефакторю прототип, поки він не досягне стандартів якості стабільного коду. Також на цьому етапі пишуться тести. Все це добре, тільки від того прототип стає ще більше та ще неосяжніше.

Тоді я починаю відокремлювати найпростіші та найізольованіші модулі та робити з них пул-реквести. Недолік: без контексту вони можуть потребувати додаткових пояснень. Перевага: кожен модуль легше зрозуміти сам по собі. До того ж такі модулі не створюватимуть ризиків, що в продукті є напівробоча частина. Останнім пул-реквестом впроваджується найвищий рівень коду, який повʼязує всі інші.

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


13.07.2023

Батчинг в Кафці та інші подробиці

Сьогодні працював над споживачем даних з Kafka та особливої уваги потребував батчинг — тобто збір вхідних повідомлень в пачки такого розміру, який є економічним для подальшої обробки. Батчинг — взагалі складна справа, бо треба не тільки набирати пачку, але й стежити за таймером. А ще думати про безпечну зупинку всього цього сервісу.

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

До речі, щодо клієнтів для Golang. Їх є немало, але знайти хороший не так легко. Баланс проходить як раз за віссю “проста абстракція — відповідність архітектурі Kafka”


12.07.2023

Спортивні додатки

Напевно, багато хто за роки карантину та війни залишився без нормального рішення для спорту. Хочу поділитися двома додатками, які для мене працюють роками.

Down Dog - неперевершений тренер для йоги. З одного боку, він генерує повноцінний відеоряд та детальні пояснення, як по позах, так і по диханню. З іншого боку, це не просто відеозапис — програма на кожний раз будується нова. Причому гарна програма виходить як на 15 хвилин, так і на годину. До того ж Down Dog має безліч налаштувань — загальний рівень підготовки, характер тренування (від “не встаючи з підлоги” до гарячої силової йоги), вибір фокуса (чудово для відновлювальної розтяжки), кількість інструкцій. Окремої згадки варте музикальне супроводження — воно складається зі цілої радіостанції, де темп треків підібраний до відповідного етапу практики. Але можна обрати й більш традиційну музику, або навіть звуки природи.

Down Dog мандрував зі мною по світу та не раз рятував від затягнутих мʼязів та інших нездужань.

Окрім йоги, Down Dog також пропонують HIIT тренування. Цими я теж колись займався. По HIIT теж купа налаштувань — наприклад, можна зазначити, що в тебе немає гантелей або болять коліна стрибати.Є навіть режим HIIT-йога фʼюжн — непогано скомбіновано. Йога виходить на заминку.

Але коли йога — то надто нудно або надто складно, є ще Seven. Вони нібито позиціюють себе як HIIT додаток, але на високоінтенсивне тренування, як на мене, їх програми не тягнуть. Та це добре: натомість Seven пропонує технічно прості, короткі (сім хвилин! насправді, з перервами — вісім) програми на кожен день. Нехитра така, але ефективна зарядка. Можливість налаштувань тут менше, ніж в Down Dog. Проте можна обрати з декількох різних курсів тренувань за своїм смаком. Гарно, що Seven можна запускати саме з Apple Watch. Погано, що тільки так він вміє відстежувати пульс та рахувати калорії.


11.07.2023

Terraform Cloud проти Scalr

Я писав про Scalr майже рік тому. Тоді ми тільки перенесли туди наше оточення Terraform. В цілому, працювало воно нормально, за єдиним нюансом. Який вони приховують з таблиці цін. А саме, кожний запуск Terraform на Scalr коштує 1 долар. Причому plan та apply - рахується вже як два запуски. Так ми не помітили, як влетіли в рахунки в пару тисяч на місяць. Як на мене, це грабіжницька політика формування цін, бо ніхто просто так запуски не рахує. (А розділення плану та застосування на два запуски то окрема образа.)

Ми не хотіли в майбутньому бюджетувати те, скільки розробки нам робити на Тераформі, тому колега Володимир знайшов та переніс нас на Terraform Cloud. Користуємося цим сервісом вже декілька місяців, та, в цілому, для наших потреб, великої різниці не бачимо.

Зокрема, функція планування витрат на Terraform, яка є у Scalr, це просто запуск Infracost, та його легко інтегрувати й в Terraform Cloud. До того ж Infracost виявився менш корисним, ніж я очікував.

Треба зазначити, що Terraform Cloud та Scalr - це єдині сервіси, які зберігають в собі стан Terraform, та тому реалізують повну систему CI - з всім іншим доведеться розміщати стан в іншому місці, а значить, також розв’язувати питання авторизації та паралельного доступу до нього. Не кажучи вже про те, що UI для перегляду стану теж не буде.

Цінова політика Terraform Cloud, на поточний момент, побудована на ресурсах. Перші 500 - безплатно, далі — кожні 10 ресурсів коштують $1/місяць. Теж може вийти дорого, але принаймні ціна зростатиме з розміром бізнесу, а не з тим, скільки планів треба запустити, щоб остаточно налагодити код.


10.07.2023

ElasticSearch - база даних як злив

На мою думку, що треба зрозуміти для ефективного використання ElasticSearch/OpenSearch - ця база у вашій архітектурі має бути стоком. Дані мають стікатись в OpenSearch в готовому, остаточному вигляді. Все, що залишається робити OpenSearch - це а) пошук та б) агрегація.

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

На практиці це значить, що дані доведеться “підсипати” до документів, що вже існують. Для цього є операція update - це зрозуміло. Що менш очевидно: ця команда здатна приймати скрипт, який виконає оновлення, замість простої заміни значень полів. Інтуїтивно мені здавалось, що цей підхід надо повільний для постійного використання. Але ж ні — оновлення скриптом працює дуже швидко, на рівні з запитами SQL. Які, власне, теж є скриптами, які треба розпарсити та виконати. Єдина різниця, що в базу SQL ми не передаємо їх в середині JSON. А так — навіть параметри до скрипту передаються окремо, так само як до підготованих запитів SQL.

Я робив маленьке дослідження та виявилось, що OpenSearch кешує вже розібрані скрипти. Тобто поки ці скрипти не є надто довгими, та ми їх не генеруємо динамічно, швидкодія сягає мільйонів оновлень на хвилину.


09.07.2023

Скрипт для підписки через RSSHub

Хочу поділитися дрібним скриптом, що я написав для підписки на RSS акаунти Twitter через свій сервер RSSHub. (У RSSHub немає ніякого інтерфейсу; для підписки треба побудувати правильну адресу стрічки для потрібного сервісу, та підписати її секретним ключем.) Нічого такого особливого в скрипті немає. Проте поки його не було, я лінувався вручну робити ті ж самі дії, та таким чином не додавав цікаві акаунти до RSS, де, як я писав, я читаю все.

Так що це гарний приклад того, як можна помітити та покращити своє оточення, навіть без значних витрат часу або зусиль. Ось весь скрипт. Він написаний мовою скриптів для Fish Shell.

function twitter_rss
    set username (string split / $argv[1])[-1]
    set code (md5 -qs "/twitter/user/"$username$secret_code)
    open "reeder://https://$rsshub_domain/twitter/user/$username?code=$code"
end

Використовується це так:

$> twitter_rss https://twitter.com/stendap_sogodni

Скрипт сам забере з адреси профілю імʼя користувача, побудує хеш авторизації, збере все це в адресу RSS стрічки, і навіть самостійно відкриє її в Reeder. Залишається тільки схвалити операцію та підписка оформлена. ((Ще є такий самий для Телеграму, відрізняється тільки адресою.)


08.07.2023

Нові розуміння про Firebase Firestore

Доробка розділу накопичень для Сінтри примусила глибше вивчити Firebase Firestore.


07.07.2023

Зони відповідальності, другий рівень

Ділюся останніми міркуваннями з самоорганізації. Минулого разу я розповідав про модель зон відповідальності. Хоч вона й дозволяла робити вичерпний огляд життя, але для пріоритизації підходила погано. А саме, зон знаходиться багато, та якщо намагатися робити щось в кожній з них, то починається перевантаження, яке вбиває кожну мою систему продуктивності. А з іншого боку, з деякими зонами пріоритизація взагалі не працює — наприклад, роботу потрібно робити щодня, навіть коли на роботі все супер.

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

Таким чином, кожна з зон верхнього рівня отримує увагу постійно — щодня або майже щодня. А зони другого рівня змагаються за увагу відповідно до стану та цілей. Групування визначає, як ми хочемо витрачати свій час. Тут можуть бути різні підходи — наприклад, я зараз створив зону “своє” з усього, що роблю на самоті, щоб балансувати це зі спільними заняттями. Можна було розділити “робота”/“побут”/“розваги”. Або “навчання”/“піклування про себе”/“суспільна діяльність”. Одним словом, це ще одна корисна модель, щоб зважити свої життєві цінності.

Як ілюстрація, я взяв пару вихідних (зона “робота”), щоб зробити дещо по ремонту (зона “дім”). Коли в ремонті вийшла пауза, то я взявся за поточний проєкт з зони “своє” - а саме, за розділ “Цілі” для Сінтри — та зробив гарний прогрес. Якби в мене був не список з чотирьох проєктів, а з тридцяти, або ста, то скоріше за все я б зробив гірший вибір. Навіть не тому, що складно їх пріоритизувати, а просто чим більше проєктів, тим легше втекти від відповідальності до чогось простішого.

Цікаво, що схожа система вже існує — це Intend.do, який раніше називався Complice. В мене навіть наліпка їхня є. Схожого тут те, що увага фокусується на невеликій кількості цілей.