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

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

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

22.12.2025

Домашня панель

За вихідні (насправді, ранок неділі) навайбкодив собі домашню панель, як і збирався цього тижня. “Навайбкодив” в цьому разі значить — не писав код самостійно. Та навіть майже не перевіряв його. Чесно, на більше немає часу, а панель потрібна — зокрема, щоб розуміти, чи електрика йде з мережі або з резерву.

Отже, який в мене зараз підхід. Спочатку я десь параграфом пояснюю, що я взагалі хочу. Здійснюю невеличкий мозковий шторм. Та в кінці пишу - “зроби мені plan.md”. Агент генерує дуже довгий та детальний план, в якому, зокрема, будуть можливі питання або рішення. Відповідаю на них. Для того виділяю питання у файлі, надсилаю в чат, та коментую. Агент заміняє питання на відповіді.

Зрештою план доповнюється всілякими подробицями — які API використовувати, які вимоги до надійності, як робити UI тощо. Як план буде мене задовольняти — відкриваю новий чат та кажу “роби за plan.md”. Воно робить з першого разу вже дуже непогано.

Ну, а потім сиджу та послідовно покращую те, що бачу. Це для мене дуже нагадує роботу в парі: я кажу, що робити, а LLM робить. На кожну нову тему створюю новий чат.

В цьому проєкті відкрив пару нових для себе режимів роботи з агентом. В одній з інтеграцій для HomeAssistant був критичний для мене баг. Пощастило, що вже є PR з виправленням. Тож кидаю агенту адресу того PRу та кажу - “застосуй його до мого HomeAssistant!” Агент зміг підʼєднатися за SSH до машини з HA, знайти відповідні файли та застосувати зміни. І це суто вбудованими можливостями Cursor, без всяких MCP.

Другий випадок схожий: ця панель розгортується на локальну машину, де стоїть сервер Lighttpd. Я в ньому не знаюся зовсім. Тож доручив агенту згенерувати скрипт, а потім ще й розібратися, чому скрипт не працює. Він також за SSH зміг виявити, що в мого Lighttpd вимкнений mod_rewrite та увімкнути. А я дивлюся та розумію: я б тільки на цю проблему вбив вечір.

А ще ця панель і вебсокетами користується, і відновлює звʼязок після відключення, і має маленьку сторінку налаштувань. У проєктах-хобі, завдяки ШІ мрії здійснюються, та я цьому не припиняю радіти.


19.12.2025

Надсилання SMS через API: ось, що я дізнався

Для проєкту сповіщень про тривоги обрав сповіщення саме через SMS. По-перше, це не покладається на інтернет, якого частіше може не бути. По-друге, в айфоні можна зробити SMS з конкретного номера такими, що будуть давати сигнал навіть в тихому режимі. (Радий буду почути й ваші аргументи.)

Але я ніколи не займався надсиланням SMS серйозно, тож які тут знайшов можливості? Вимоги в мене трохи специфічні, бо я не планую надсилати понад 500 SMS на місяць, причому лише на 2-3 номери. Більшість сервісів орієнтовані на розсилки.

Пішов до найвідомішої компанії спочатку, тобто Twilio. (Це ті, кому належить Sendgrid, але починали вони з SMS.) Кредит їм вніс. Та тут виявилося, що SMS на українські номери тут коштує близько 50 грн. Ну якось забагато для хобі, що вам сказати. До того ж українських номерів вони не дають, хоча то вже справа друга, аби надсилали. Зате в Twilio є Go SDK.

Коли побачив ті ціни, знайшов українську альтернативу - TurboSMS. Тут вже близько 1 грн за SMS. Є HTTP API. В цілому, воно працює! Але: тут надсилання йде не з телефонного номера, а з іменованого відправника. Імена ці проходять реєстрацію в Національному реєстрі, то ж це ціла довга історія, яка мало зрозуміла для мого проєкту.

Щоб не реєструвати імʼя, можна скористатися одним з вбудованих: наприклад, InfoClub. (Це пояснює, чому я часто бачу сервісні SMS від різних сервісів, але з одного відправника. З 2FA так часто буває.) В цілому, робоче рішення, але зʼявилася інша проблема: айфон не дозволяє додати іменованого відправника в контакт. А значить, налаштувати завжди гучні сповіщення для нього не вийде.

Після того як зрозумів обмеження іменованого відправника, пішов шукати сервіси віртуальних телефонів. Такого теж багато! Поки опинився на Zadarma. Тут ти обираєш звичайний номер — як коли купуєш сімкартку. Потім цей номер стає доступним для отримання та здійснення дзвінків та SMS. Тут теж є HTTP API. Проте теж — перевірка документів перед тим, як віддадуть номер. Сподіваюся, за кілька днів відзвітую про остаточний успіх.

PS: а ще надсилання SMS всюди вимагає підтвердження особи — певно, щоб запобігти спаму.


18.12.2025

Redis - що воно таке?

Одним реченням: Redis - це сервіс оперативної памʼяті. Почекай, скажеш ти, а навіщо нам цілий сервіс для памʼяті? В нас вже є памʼять вдома.

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

Головною перевагою Redis над базою даних є те, що в Redis всі дані завжди знаходяться в оперативній памʼяті. Це дозволяє надати чіткі гарантії швидкості. Можна бути впевненим, що поки упрешся в навантаження, запити будуть завжди швидкими. Звісно, ця особливість також значить, що розмір Redis обмежується розміром памʼяті машини, тому Redis не універсальна база даних.

Очевидно, що доступ до Redis буде помітно повільніше за звичайну памʼять. Тому там є просто величезний API. Тут можна не просто читати та записувати значення, а брати готові рішення. Навіть для геоданих чи часових послідовностей. Та й вище згаданий кеш покладається на можливість встановити час спливу значень. (Це, мабуть, найперше, чим користуються.)

Якщо й всіх API мало, всередині Redis навіть можна виконувати скрипти на Lua! Та таким чином обійти ті обмеження повільного доступу — вибудувати з низькорівневих операцій власну бізнес-логіку.

Також Redis вміє зберігати власний стан на диск та навіть вести журнал для надійності. Головне памʼятати, що дані все одно повинні влазити в памʼять — це фундаментальна особливість.

Redis одна з моїх улюблених баз. Вона зрозуміла, швидка, та надійна. Та, принаймні у веброзробці — завжди десь поруч.


17.12.2025

Redis як спільна памʼять

Типово я звик бачити Redis як кеш чогось, ну або як нішеву базу даних (бо, знаєте, хоч Redis і тримає все в памʼяті, там є можливість зберігати зміст на диск.)

Але хочу звернути увагу на інше бачення: Redis є спільною оперативною памʼяттю між багатьма вашими процесами чи машинами.

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

Але й у вебзастосунках є стан. Класичний приклад: обмеження частоти запитів. В межах однієї машини його робити нема сенсу, зате лічильник можна покласти в Redis. Є навіть офіційний посібник.

Redis достатньо швидкий: лише на 1-2 порядки повільніше за звичайну оперативку, та, наприклад, на порядок швидше ніж локальний SSD. (Єдина порада - не складати в один запис надто багато. Краще, коли це буде окремий примітив чи невеличкий обʼєкт.)

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

Може, у вас є сервіс, який спирається на внутрішній стан, та через це його ніяк не виходить масштабувати - або хоча б тримати в двох екземплярах для надійності. Redis прийде на допомогу.


16.12.2025

Як пошук LIKE взагалі може бути швидким?

Дивись, є в тебе запит: SELECT timestamp FROM logs WHERE message LIKE *failed*. Як можна реалізувати його в базі? (Повнотекстовий пошук поки взагалі забудемо, бо він ще складніший.)

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

Та дійсно, навіть за наявністю індексу базі доведеться попросту перебирати всі значення. Звісно, що це буде… повільно. Втім, на допомогу нам прийде індекс за триграмами. (Ну, або N-грамами, узагальнено.)

Триграма — це шматочок тексту довжиною до 3 символів. Наше поле розрізаєaться на всі можливі шматочки:

request failed => r, re, req, e, eq, equ, ... led, ed, d

(Шматочки з одним та двома символами потрібні для коротких запитів. Хоча, скільки разів ти бачив “Для пошуку введіть хоча б 3 символи?” Тепер знаєш, чому.)

Тепер ми будуємо таке саме “традиційне” дерево пошуку, але вже для кожної триграми. Потім, пошуковий запит теж розрізається:

failed => fai, ail, ile, led

Ми шукаємо записи для кожної триграми окремо, а потім перетинаємо результати. Залишається тільки зробити зачистку, щоб прибрати небажані результати, наприклад, fai ail ile led - цей перебір займає вже зовсім трохи часу.

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

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


15.12.2025

Плани на решту грудня

Збираюся підготувати для сімʼї певну інформаційну панель. Хочу показувати графік відключень, стан резервного живлення, стан повітряних тривог. Все це у зручному вигляді.

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

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

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

Отже, моя ідея — залучити тут LLM. Наприклад, LLM легко здатна прочитати вище згадану сторінку та побудувати структурований в JSON чи iCal графік відключень для заданої групи. Повірте, я за своє життя не раз намагався зробити схожий парсер вручну — це нереально зробити повністю та важко зробити хоч якось. Це саме та задача, для яких існують нейронні мережі.

Ось так. Радий буду почути, якщо хтось вже робив щось схоже.


12.12.2025

До оптимізації можна підходити з різних боків

От є в тебе певне місце в застосунку, де все гальмує через запити до бази. Та ти, звісно, хочеш цю ситуацію покращити. Але як?

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

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

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

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

Головне — не поспішати зі змінами, щоб не наробити дурниць. Озирнутися ширше, спитати порад. А потім вирішувати, що робити та якою ціною.


11.12.2025

Розумне світло із HomeAssistant, Philips Hue та Shelly

Перший з кількох постів про реалізацію електрики для мого санвузла. Так, там матеріалу на маленьку книжку!

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

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

Отже… Почнемо зі стельового освітлення. Довго перебирав варіанти та зупинився на Philips Hue Enrave S. Насамперед це якісні LED та добротна побудова. Але також я був впевнений, що з Hue буде працювати Home Assistant, та не створить проблем. Так, в цілому, й вийшло.

Є тільки один нюанс: будь-яка лампа Hue не буде працювати з класичним вимикачем, бо її електроніка мусить бути завжди заживлена. Отже, між лампою та вимикачем буде розумна начинка. Але… якщо HomeAssistant чомусь не працює, світло повинно вмикатися й без нього. Повір моєму досвіду — не роби розумний будинок без резервного керування, бо залишишся без зручностей в найбільш незручний час.

Знайомся — реле Shelly Plus 2PM. Я вже писав про нього, але в цьому проєкті реле розкривається ширше. В нього є два виходи — як раз на ванну та туалет — але також два входи, до яких підʼєднується той самий класичний вимикач.

В цього реле вже достатньо мозків, щоб керувати виходом зі входу. Але таке нам не треба, памʼятаєш? Тому насправді в HomeAssistant сидить автоматизація, яка слухає стан входу реле та передає Philips Hue команду увімкнення чи вимкнення. А виходи реле залишаються заживленими завжди.

Та тепер останній момент — що ж робить коли HA зліг? Власне, що мене переконало в виборі реле — це те, що на ньому можна також виконувати скрипти — на JavaScript. Та я знайшов скрипт, який перевіряє доступність HA та перемикає реле в незалежний режим, коли HA немає. Це ж фантастика!

І все це, звісно, тільки початок всієї реалізації.

(PS: не припиняю вражатися, що малесеньке реле, яке влазить за вимикачем в стінну коробку, містить в собі цілий компʼютер із Wi-Fi, Bluetooth та так, навіть віртуальною машиною JavaScript!)


10.12.2025

Програмування займає весь наданий час

Ще одна тема від пана Степана.

Програмісти — цікаві працівники. (Або це програмування — цікава задача.) Під час дай їм тиждень на задачу — зроблять за тиждень. Дай місяць — зроблять за місяць. Взагалі не давай ніяких обмежень — можуть й три місяці полірувати.

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

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

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

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


09.12.2025

Вихід від інженера — його рішення

Дякую за цю тему пану Степану.

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

Справжньою цінністю, яку приносить інженер, є його рішення.

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

Видатний інженер здатний знаходити неординарні рішення, думати поза обмеженнями, переосмислювати задачу. Не просто “писати код”. Та дійсно, рішення певного рівня цілком можна віддати на LLM та вона зробить їх не гірше. Це тільки значить, що людські рішення підносяться на вищі рівні. Та, в цілому, так і будується моя робота з LLM: я роблю рішення високого рівня та передаю їй написання коду.

Мабуть, це вимагає певної впевненості в собі та сміливості. Бо, власне, коли ти не вирішуєш сам, а звертаєшся до керівника, то тим самим окреслюєш свій рівень та свою сферу відповідальності. Звісно, за власні рішення доведеться відповідати, в цьому і є цінність твоєї посади. Знову-таки, LLM згенерує що завгодно, але відповідальною не буде ніколи. Ти її керівник.

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