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

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

Підписатись на RSS · 📢 Канал в Telegram @stendap_sogodni

07.09.2024

Розгортування в хмару, чому ти таке повільне?

Величезним мінусом всілякої хмари, порівняно з розгортуванням на конкретні машини, було те, як воно до біса повільно розгортується. Як з Heroku почалося -надцять років тому, так і зараз тільки гірше стало.

Повільно все тому, що ми не володіємо в хмарі ресурсами. Це як якби щоразу перед тим як їхати кудись на машині, потрібно було її взяти в оренду. І не зручним Гетьманкаром, а через заповнення документів та пошук машини на стоянці.

Відповідно, хмарний сервіс повинен знайти для нас потужності, потім завантажити наш код (або величезний образ Docker), запустити, пройти перевірки, зупинити старі контейнери. Heroku взагалі чудову абстракцію побудували, коли знаєш, що всередині.

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

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


06.09.2024

Список для читання через два роки

📖 Списком для читання я користуюся практично щодня. Через те мені не потрібна сотня вкладок.

⏲️ Список для читання гарно працює, коли нічого в ньому не має терміновості. Раніше я користувався ним як буфером для всього, що не зможу закінчити зараз — статті, відео, товари, документація. Але, коли список розростається (а так і буде), то все орієнтоване на задачі в ньому губитиметься.

📝 Тому тепер, коли зустрічаю сторінку, яка не просто цікава, а саме зараз, то записую її в Drafts, де побачу (та оброблю) протягом тижня. (До речі, що в Reeder, що в Drafts, та багато куди ще легко зберігати через функцію “Поділитися” на macOS та iOS.)

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

📺 Також нещодавно почав “список чого подивитись” - просто в Reminders - та так само як список для читання, він допомагає в зручний момент дивитись щось цікаве, а не просто випадкову “піну” з YouTube.

🔎 Ще натрапив на таку зручну функцію, як попередній перегляд посилань в браузері Orion. Вона працює поза браузером та відкриває посилання в тимчасовому вікні — яке за бажанням можна “розгорнути” у звичайну вкладку. Це дуже спрощує перегляд посилань з Obsidian чи з Slack - браузер не захаращується випадковими вкладками.


05.09.2024

Sentry та обмеження обсягу

Почалося все просто з того, що я перевіряв, як працює інтеграція slog з Sentry з вчора. Нічого тут складного немає. Береш ключ з проєкту. Запускаєш з ним локальний скрипт. Скрипт надсилає помилку в Sentry. От тільки… ні. Чомусь не надсилає.

Звісно, спочатку намагався знайти, що роблю не так. Фільтри, налаштування… Ніби все працює. Навіть sentry.CaptureMessage повертає якийсь ідентифікатор. Але на сайті порожньо.

Точніше ні. На сайті були свіжі випадки якоїсь іншої помилки. Тож Sentry живий. Такого я раніше не бачив. Від розпачу вирішив виправити ту іншу помилку, бо обсяг був немаленький.

Поки шукав, звідки вона взялася (а справа була на стейджингу), помітив, що помилка належить до релізу за травень. Такого старого коду просто не могло бути — але десь він був запущений. Та сипав помилками.

Урок: додавайте до помилок достатньо метаданих, щоб відстежити її до сервісу. Мені довелося шукати в декількох кластерах ECS, бо відома був тільки IP адреса зі спільної для них мережі. Така задача простіше з AWS CLI та jq.

Все одно не відразу знайшов, бо та IP адреса належала вже зупиненій задачі. Яка з травня висіла в очікування зупинки. Поки не знаю, чому, але моя ставка на багах ECS. Задачу вдалося зупинити через примусову зупинку машини EC2. Взагалі я трохи в шоку, бо в теорії така “зомбі” могла б накоїти гірших наслідків. Доведеться придумати, як за цим спостерігати.

Помилка зникла. Можна було повернутись до перевірки інтеграції та… о диво, вона запрацювала! Виявилось, що стара помилка вичерпувала rate limit проєкту, тому нова й не могла проскочити. Урок 2: треба дуже уважно ставитись до обмежень обсягу в Sentry, бо якщо вони вичерпуються постійно — навіть чимсь неважливим — то є реальний шанс не побачити нову помилку, навіть критичну. Плюс один показник, за яким потрібно стежити.


04.09.2024

Пригоди з логуванням в Golang

Вже десь рік в Go є вбудований модуль для структурного логування - log/slog. Нарешті наважився на нього переїхати. (Структурне логування — це коли в лог пишуться не просто рядки, а структури. Найчастіше - JSON. Тоді з нього легко дістати будь-яке значення.)

Коли б тільки зі старого стандартного логування, то це більш-менш нескладно. Ну хіба потрібно буде шаблонні рядки перетворити на структурний синтаксис. Та де-не-де замінити log.Fatal на щось власне, бо в slog такого немає. Що може й непогано, бо log.Fatal виходить з програми миттєво та пропускає всі блоки defer - в тому числі можливо, й ті, що фіналізують журнал.

Бо логи не обовʼязково йдуть тільки у стандартний вивід. Помилки також направляються в Sentry. Є різні способи це зробити — мені подобається само надсилати логи. Sentry - чудовий сервіс, але все одно всі помилки варто бачити в журналі. Зі структурним логуванням в Sentry та в журнал йдуть практично однакові дані. Та й синтаксис slog краще.

Для структурних логів у нас вже був logrus. Тож його теж потрібно було замінити. (Разом з його інтеграцією в Sentry.) Можливо, легше було б зробити для logrus та log адаптери до slog, а потім вже поступово переписувати. Хоча мені миліше зробити все за один раз, та ще й прикрити лінтером forbidigo, щоб заборонити все, окрім slog.

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


03.09.2024

В стрімі про пригодницьку гру 11th Hour побачив цікаву головоломку (До речі, цей канал ведуть головний актор старої пригодницької гри Phantasmagoria 2 разом з чемпіоном по спідрану тієї ж гри. Рідке поєднання!)

Головоломка механічно проста, проте швидко виявляється, що коням немає де розгорнутись. Знаходиться “центральна” точка, до якої зручно дістатись, але рухатись далі заважають інші коні. Поки дивився, як ведучі страждають, згадав, що воно мені нагадує. Це ж граф!

Якщо побудувати з можливих пересувань фігур граф, то розвʼязок стає не те що легким — а очевидним. Мораль тут в тому, що побудова правильної моделі задачі це половина розвʼязку.

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

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


02.09.2024

З Obsidian Canvas у список задач

Не так давно писав про генерацію Obsidian Canvas зі списку. Сьогодні переді мною стала зворотна задача. В канві накопичилася купка задач та я хотів перекинути їх у список. (Бо саму канву як список задач складно використовувати.) Отже, проста людина перекопіювала б ті задачки за декілька хвилин. Але ж мені потрібно автоматизоване рішення.

Дописав до утиліти pbcopy-chromium з попереднього поста режим вставки: тобто тепер вона може вивести зміст буфера обміну Chromium - наприклад, вузли канви. Бо конвертувати цілий файл то гарно, але на практиці сьогодні пені потрібні були лише декілька вузлів.

Далі в мене є нехитрий скрипт на Ruby, який обходить спрямований граф вузлів та будує з них список в Markdown. Це така задача, яку в повному обсязі буде досить складно розвʼязати (бо є цикли, орієнтація вузлів в просторі, різновиди стрілочок-ребер), але якщо обмежитись обумовленими, “нормальними” графами, то це традиційний обхід в глибину.

На Markdown історія не закінчується, бо ті списки в мене сидять в Reminders.app. А туди Markdown не вставиш. (Та й взагалі можливості вводу-виводу мінімальні.) Знайшов поки тільки ручне рішення — скопіювати список у Notes.app, там перетворити його на “список задач”, та ось цей “список задач” вже можна скопіювати у Reminders. Поки не знайшов, як то автоматизувати, бо формат буфера обміну тут знову закритий, com.apple.notes.richtext, та бозна-як з ним працювати.


01.09.2024

Спостереження за змінами на сайтах

Купа задач зводиться до спостереження за сайтами. Оновлення, розпродажі, оголошення — не завжди нам повідомлять про них напряму. Перевіряти вручну — непрактично.

Тобто, гарно, коли є підписка на RSS, або поштою, або принаймні надійна стрічка в соціальній мережі. Зокрема, я підписаний на RSS декількох сторінок “Releases” на GitHub. (Для того до адреси сторінки просто дописуємо .atom.)

Але на жаль, не у всіх воно є та працює надійно. У нас нещодавно був випадок, що офіційна розсилка деякого продукту про нову версію “забула”, а сторінка змін оновилася. На щастя, було налаштоване спостереження за сторінкою через Zapier, тому версію не проґавили.

Спостереження за змінами — на перший погляд, найпростіше, що може бути. От тільки проблема в тому, що більшість вебсторінок змінюються постійно — можливо, при кожному перезавантаженні — тож доведеться розумно обмежувати область порівняння. Якщо вже робити перевірку власноруч, то я б обмежувався змістом конкретного селектора, або присутністю регулярного виразу в тексті, а не в коді.

Є гарний продукт з відкритим кодом changedetection.io. Він вміє відстежувати частину сторінки, а ще аналізувати інформацію про товари. Що, до речі, дуже потужний спосіб заощадити на не терміново потрібних речах. Закинув вудку та чекаєш на приємний сюрприз. Є в них і платний SaaS.


31.08.2024

Fish Shell

🐠 Є багато текстових оболонок, гарних та цікавих. В мене - Fish. Це, певно, третя чи четверта за популярністю оболонка після Bash та Zsh.

Девіз Fish - “оболонка для 90-х” - непогано підкреслює її особливості. Тобто порівняно з Bash чи Zsh, вона має приємніший синтаксис та деякі цікаві можливості як вебінтерфейс для налаштувань. Але також тут немає нічого революційного — оболонка як оболонка, більшість команд та підходів збігаються.

Як одна з все ж популярних оболонок, Fish користується підтримкою у більшості доповнень (як direnv) та терміналів (як VSCode).

Також для Fish є декілька менеджерів плагінів, в мене встановлений fisher. (Плагін — то просто набір конфігураційних файлів.) До речі, подобається в fish зручний та зрозумілий каталог конфігурації. Як завжди, багато є різних плагінів для красивого рядка команди, але в мене він спрощений максимально, бо я користуюся терміналом через VSCode.

Мова скриптів Fish досить зручна, я час від часу дописую щось своє. Хоча скрипти для проєктів все одно всі на Bash, щоб були переносними. Так що доводиться памʼятати ще одну рідко використану мову.

Взагалі, чого мені не вистачає в терміналі, це повноцінного редактора командного рядка, де можна виділяти, копіювати, і таке інше. Не знаю, де його таке шукати — може, ви знаєте?


30.08.2024

Попередній перегляд постів в Telegram

Почав з реалізації попереднього перегляду для Telegram, бо тут вже більше коду готово. Виявилося, базовий тестовий скрипт не так вже й складно зробити. Чим воно відразу відрізняється від звичайної функціональності Hugo - замість всього сайту перегляд працює тільки з одним постом. Звісно, того ми й хочемо, але: тоді ще й потрібно щоб користувач обрав пост, над яким працює. (Або ні… є ідеї.)

В основі лежить спостереження за змінами в файлах; випробував новий для мене модуль fsnotify для Go. Він робить приблизно те, що від нього й очікуєш; хіба що не вміє стежити за деревом каталогів — але поки мені взагалі достатньо й одного файлу.

Далі, в тестовому каналі в Telegram створюю порожній пост. (Можна було б навіть брати останній, але технічно простіше створювати новий на кожний запуск скрипту.) Пост можна скільки завгодно редагувати, причому він оновлюється в клієнті наживу, навіть з прокруткою до нового змісту.

Залишається отримувати події про зміни з fsnotify, перемальовувати пост (тобто конвертувати з Markdown в Telegram HTML), та надсилати через API. Обмеження на частоту запитів значення не мають. Єдине, що Telegram не дозволяє надсилати новий зміст такий самий, як наявний. Але то дрібниці.

Певно, найскладнішою частиною було видерти з того скрипту, що вже є, саме промальовку. Бо, уявляєте, там водночас відбувається і промальовка, і валідація, і таке інше. Поки рішення на рівні “накопіпастив та повидаляв зайве”. Взагалі з публікацією в декілька сервісів буде цікаво, бо наразі читання метаданих та конвертація Markdown в HTML логічно спарені.

Поки дуже задоволений, прототип вже спрощує життя.


29.08.2024

Публікація в Mastodon: попередній перегляд

Публікація в Mastodon в мене трохи загальмувала, хоч технічно рішення ніби готове. Тобто перетворення поста на HTML для Mastodon та публікація готова.

Мій сервер у Федіверсі - GoToSocial - поки не вміє редагувати пости. Взагалі у Федіверсі редагування — не така вже й проста дія, бо потребує реплікації на інші сервери. Втім, в Mastodon для редагування є API.

Отже. Так чи інакше, перед публікацією пости варто переглянути (та відкоригувати.) В Telegram я робив це “наживу”, бо мій скрипт вміє редагувати вже дуже давно — тож я можу опублікувати, а потім зробити декілька правок. Щоб це помітити, треба прямо уважно дивитися на свіжий пост. (Хоча, сповіщення отримують початковий текст. Також міст в RSS може зберегти старий текст, якщо йому пощастить.)

А з Mastodon такої можливості не буде. Навіть якщо редагування є, я боюся що по децентралізованій системі розповзуться недороблені варіанти поста. Тому, зробити кроспостинг заважає відсутність попереднього перегляду. Особливо якщо винести публікацію на CI, щоб поєднати з публікацією вебсайта.

До речі, рушій мого сайту - Hugo - містить чудовий локальний сервер з живим перезавантаженням. От щось схоже хочу зробити для Telegram та для Mastodon.