Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS · 📢 Канал в Telegram @stendap_sogodni
11.07.2024
Go-global та важливість правильного повідомлення про помилку
Несподівано з новим застосунком натрапили на таку помилку в go-global:
global: : cannot write param: config key is of unsupported type struct
(Go-global це наша бібліотека для завантаження структур параметрів. Останній раз оновлював її ще рік тому, втім, зазвичай вона свою функцію виконує та проблем не створює.)
По-перше, незрозуміло, чому struct
не підтримується, бо звісно ж на них вся конфігурація й побудована. Справжній зміст помилки в тому, що ми примітивне значення намагаємося записати в поле структурного типу. Тому так і написав:
cannot write param: destination should be a primitive type, not a struct
По-друге, дивно: повідомлення про помилку мало б містити шлях, за яким вона відбулася. Переглянув код та ніби все так і працює… тоді роздивився уважніше помилку та зрозумів, що друга двокрапка global: :
і є шляхом, точніше, шлях порожній. А порожній він не тому, що щось поламане, а тому, що помилка відбулася на верхньому рівні. Так не повинно бути, бо за логікою там не може бути параметра — завжди є хоч би один рівень вкладеності.
Виявив, що параметрів на цей раз зовсім не було. Це утворювало “порожній” верхній рівень… а далі, через збіг обставин, він розглядався як “листок”, та й призводив до помилки. Тобто що дійсно треба побачити користувачу, це попередження про відсутність параметрів:
no parameters in Parameter Store with prefix "/foo/"
Отакої! А без вірного повідомлення навіть я як автор бібліотеки не міг зрозуміти, де криється справжня помилка.
10.07.2024
Перегляд журналів до CodeDeploy
Ми використовуємо AWS CodeDeploy для розгортування сервісів. Якщо чесно, єдине що про нього можу сказати хороше — це те що він добре інтегрований в Amazon та дозволяє робити безпечне розгортування за декількома моделями на вибір. Але в користуванні він жахливий.
Зокрема, дуже складно шукати причину, чому розгортування не вдалося. (А на стейджингу це відбувається досить часто.) В CodeDeploy немає, як це не дивно, явного звʼязку з конкретними екземплярами сервісу та їхніми логами. А якщо до того згадати, що ECS “забуває” задачі десь через годину після зупинки, то відстежити відповідність розгортування до логів стає кропіткою та терміновою ручною роботою. Та це ми навіть не почали дивитися на саму проблему!
Отже, сьогодні з цим щось зробив. Написав скрипт, який знаходить ті самі журнали та зводить їх в зручну форму. Причому робить це автоматично, з посилання на розгортування.
Для того довелося: з API витягнути розгортування; потім з нього “специфікацію застосунку”; потім з неї “дефініцію задачі”, а також назви Lambda-функцій, що роблять перевірку на здоровʼя; нарешті по назвах знаходжу конфігурації функцій, та з них та дефініцій задач можна здобути групи журналів, які стосуються розгортування. Фух! Не тільки складно, але й досить спеціалізовано; мабуть, саме через це вони самі логи й не показують.
Але це ще не все… з груп залишилося знайти потоки. (Я колись писав, що в Cloudwatch “потік” відповідає конкретній задачі.) Для того я більш хитрим, ніж базові API, шляхом відтинаю всі потоки, які не збігаються за часом. (Як не дивно, такого API немає; максимум це перелічити потоки за зменшенням часу.)
А потім всі результати складаю в шаблон HTML та відкриваю в браузері. В терміналі теж гарно, але я може ще якийсь UI додам зверху.
….Альтернативним шляхом було б формулювання запиту до Cloudwatch Insights. Тоді можна було б зупинитися на групах + діапазоні часу розгортування. Так, може, було б і краще.
09.07.2024
MX записи — адресна книжка електронної пошти
Широко кажучи, електронна пошта набагато сильніше привʼязана до адресата, ніж до відправника. Відправником може бути буквально будь-хто в інтернеті, особливо якщо надасть ознаки довіри, але й це не обовʼязково. А от адресат обовʼязково сполучений з доменом своєї адреси, бо саме туди будуть надходити листи.
Для того в стандартах DNS передбачений особливий тип запису: MX
. Він вказує з домену отримувача на домен поштової скриньки. Це практично єдиний сервіс, ушанований такого місця; так, пізніше зʼявилися записи SRV
, які можуть вказувати на будь-який сервіс, але відокремлений тип є тільки для пошти.
Коли ми хочемо передивитись вебсайт, то знаходимо його IP адресу. А от якщо надіслати листа — то робимо окремий та особливий крок: шукаємо MX запис, а потім вже так само IP адресу, але вже скрині, на яку вказав MX-запис.
(Відзначу, що механізм CNAME, яким ми користуємось для делегації сайту на хостинг, працює кардинально інакше, але це варто окремого поста.)
Таким чином, отримувати пошту для домену може будь-який інший домен. Може, це GMail чи Outlook. Може, спам-фільтр. Може, сервіс “поштового API”. Ба більше, MX записів може бути навіть декілька, та це “не баг, а фіча”: так можна налаштувати балансування навантаження або додати резервний сервер на випадок відключення. Це є джерелом помилок, бо коли люди змінюють провайдера поштової скрині, то можуть не знати, що старий необхідно видалити з MX.
MX-записи не мають жодного відношення до надсилання пошти. Хоча, у форматі SPF є можливість “благословити” надсилання з MX-записів - але це тільки для зручності. Бо сервер для надсилання міг збігатися зі скринею — але це скоріше випадок маленьких, “гаражних” архітектур, якими вже ніхто майже не користується. Якщо у вас MX - це GMail, то надсилати GMail буде зовсім з інших вузлів.
08.07.2024
Помилка повтореного заголовку з ActionMailer
Сьогодні випустив нову версію бібліотеки mailtrap для Ruby. Це було вмотивовано виявленням цікавого збігу обставин, який псував, хоч і не суттєво, зміст листів, які надсилалися через Ruby on Rails.
Яку проблему помітили: в листах було два заголовки MIME-Version
(а точніше, другий Mime-Version
, тобто очевидно заголовки приходили з різних місць.) Це не призводить до помилки (головне, щоб такий заголовок був.) Але це один з заголовків, які будуть включені в підпис DKIM; та так складалося, що з подвійним заголовком підпис був не до кінця вірним (деякі сервери звертають на це увагу та знижують репутацію листів.) Тому необхідно було позбавитись того зайвого заголовку.
Що робити? Можна, звісно, вичищати той заголовок на виході, але тут треба обережно знайти системний підхід. Простіше спочатку зрозуміти, звідки він взявся — тим паче що очевидно, система-джерело робить зайве.
Причину я знайшов: ActionMailer до того, як передати листа на доставлення, викликає в нього метод encoded
. А той метод зрештою додає той самий заголовок. Все було б більш-менш добре, якби лист надсилався за SMTP; але оскільки він йшов у наш API, то всі заголовки, які є, передавалися як “особливо замовлені”. А наш API, коли будує листа, теж додає MIME-Version
за стандартом. Така вийшла плутанина з відповідальностями.
Цікаво також, що ми не знайшли цей збіг, бо не тестували повний цикл разом з застосунком Rails, а тільки починаючи з готового обʼєкту Mail::Message
. Тобто все б нічого, але метод encoded
ніхто не викликав. Власне, щоб виправити помилку, я спочатку його додав та зламав тести.
А взагалі, некрасиво в методі, який ніяк не натякає на мутації, змінювати обʼєкт та ще й таким суттєвим чином.
07.07.2024
Побудова плану квартири, або фотограмметрія в домашніх умовах
Була в мене задача: побудувати план квартири, до якої немає постійного доступу. Та ще й зі стінами, дверми, вікнами. Знайшов підхід, який може й непрофесійний, але результат дав.
-
Переміряв всі стіни лазерною рулеткою. Вона надзвичайно допомагає у вимірюванні просторів, бо звичайну рулетку часто або неможливо протягнути, або принаймні непрактично. Навіть коли кімната порожня, двері чи вікна можуть перешкоджати. Плюс з лазерною впорається одна людина. Та вимірювання робляться миттєво.
-
Перефотографував кожну стіну (от вам і фотограмметрія.) Намагався мінімізувати перспективні викривлення; для того потрібно фотографувати перпендикулярно до поверхні та навпроти її центру. Так не завжди вийде — наприклад, в коридорі.
-
З вимірів на компʼютері зробив макети… у Pixelmator Pro. Я не знайомий зі справжнім CAD, а щось для початківців не знайшов. Головне, що в Pixelmator можна задавати розміри прямокутників в цифрах: я обрав один піксель = один міліметр. А також те, що при пересуванні прямокутники прилипають один до одного; так насправді досить швидко можна зробити точний план без деталізації. Лише раджу вивчити клавіатурні команди.
-
Залишилась деталізація (розташування дверей, вікон тощо.) Вимірювати все це рулеткою на мою думку непрактично, або принаймні якщо не знаходишся на обʼєкті. Тому визначав розміри за підготованими світлинами.
-
Там, де був лінійний орієнтир (повторюваний малюнок на шпалерах або підлозі), було легше — можна просто порахувати елементи на око. А ось там, де ні, було цікаво. Брав світлину стіни, коригував її перспективу (в тому ж Pixelmator), а потім — коли стіна стала прямокутною — розмір, відповідно до вимірів. Таку скориговану світлину можна копіювати на макет та обводити (або навіть залишити, як є.)
До того думав креслити все вручну на папері; але у Pixelmator вийшло не тільки чіткіше, але ще й швидше. Та цей цифровий план легше буде використовувати повторно. Pixelmator 1 : папір 0.
06.07.2024
Стискання шрифтів для вебу
Закінчую роботу над значками для Obsidian. Як минулого разу казав, шрифт значків всім гарний, от тільки завеликий за розміром. Взявся обрізати шрифт, щоб залишилася тільки та купка значків, яку я використовую.
На то знайшов бібліотеку fontTools - до речі, ще один продукт на Python, який треба встановлювати на пайтонівський намір. Ну, зате, на щастя, brew install fonttools
теж працює. Бо всі ці pip
та virtualenv
то просто жах.
FontTools вміє багато всього, а мені була потрібна команда subset - вона саме й обрізає шрифти під замовлення. Приклад можна побачити на знімку вище. Взагалі все дуже прямолінійно: даєш шрифт, даєш символи чи їх діапазон — та готово.
Працює навіть надто гарно, бо я довго не міг зрозуміти, чому ж на виході “порожній” файл у 1 кілобайт. Ну не може пʼять значків влазити в 1 Кб! А виходить, що можуть — переконався, коли нарешті наважився перевірити результат на ділі. Тепер мені рішення зі шрифтом для значків подобається ще більше.
Нарешті, тією ж командою можна перекодувати шрифт у WOFF2. Дописав також скрипт, який відразу загортає його в .scss
, щоб не робити цього вручну кожного разу, як додам новий значок.
05.07.2024
Тредізація RSS Twitter
Трохи невдала сьогодні спроба. Хотілося у стрічці RSS для Twitter, яку генерує RSSHub, бачити треди в одному пості — бо як окремі пости, їх досить складно сприймати. Взагалі проблема витікає з того, що з API неможливо витягнути твіт, на який зроблена відповідь — тільки його URL. (Та й взагалі той API вже “не той”, та Twitter вже “не той”, та я б із задоволенням про нього забув, проте багато журналістів та дослідників більше нікуди не публікують.)
Ідея була проста: спід час генерації стрічки RSS виявляти ті твіти, що відповідають на інші твіти з того ж RSS, та “підшивати” один до одного. Тут не потрібні додаткові звернення до API - тільки додаткова обробка. Ніби все просто та прототип я навіть зробив, але на практичній перевірці ідея не запрацювала.
Річ у тім, що твітів в одній виборці близько 20, та вони навіть не впорядковані за часом — а, певно, за популярністю чи ще якимсь алгоритмом. Через це у вибірку може потрапити, наприклад, перший та останній твіт у треді — а решта ні. З такого вже кашу не звариш.
Та друга проблема: у вибірку може потрапити не весь тред. Спочатку я думав, що це не так погано — умовно, замість 40 постів в стрічці буде не 1, а 2. Але: при наступному оновленні межі вибірки зсуваються не повністю. Виходить, можна отримати хоч 10 напівдубльованих шматків. Щоб цього уникнути, можна залучити кеш та зберігати попередні пости. Але це вже ускладнення на майбутнє.
До речі, розробляти для RSSHub напрочуд просто; це застосунок Node.js, та запускається він за yarn install && yarn dev
. Навіть TypeScript та Prettier в них є. Навіть Codespace підготований! Так що, можливо, власні RSS генератори теж перенесу у RSSHub.
04.07.2024
GitHub Codespaces: на диво гарно!
Сьогодні мав перший досвід роботи у GitHub Codespaces. Це, так би мовити, “хмарне робоче місце”: віртуальна машина з приєднаним редактором, на якій можна вести розробку. Перші враження такі, що це дуже гарне рішення, та якщо вам щось таке потрібне, можна не вагатися.
Перше, що помітиш, це безшовна інтеграція з VSCode. Одна з визначних, хоч і прихованих можливостей VSCode - це клієнт-серверна модель виконання. Тут вона працює на повну, та віддалений проєкт практично не відрізняється від локального. (Єдине, що термінал — не редактор — все ж гальмує, але і тут вони помʼякшили: все введене в термінал моментально зʼявляється “примарними” літерами, а після обробки на сервері вони стають звичайними.)
Зміст проєкту береться з репозиторію GitHub, що очевидно. Також під час створення кодспейсу він питає гілку — а це трохи спантеличило. Але мається на увазі гілка із конфігурацією кодспейсу, яка тут робиться у форматі devcontainer. Далі ми вільні переходити в будь-яку гілку та й взагалі робити, що хочемо. Також можна надати доступ до інших приватних репозиторіїв. Технічно можна навіть створити кодспейс з порожнього репозиторію, а потім підтягнути туди абсолютно інший код.
Всередині отримуємо більш-менш стандартну віртуальну машину з Debian. Головне, що Docker працює. Також маємо можливість доналаштувати, причому, що мені подобається: як спільне для всіх оточення, так і персональне (за допомогою dotfiles). Оце важливий момент: Codespaces це інструмент для команди, тобто досвідчений інженер може налаштувати середовище, яке потім легко запустить будь-хто з колег.
Це приводить нас до питання: кому таке потрібно? Та, як на мене, саме оказійним розробникам. Наприклад, може у вас є підпроєкт, який не всім та не завжди потрібний; можна налаштувати для нього кодспейс та будь-хто з команди зможе долучитися з дрібними змінами. Або інший випадок: для безпеки та ізоляції. Щоб код проєкту та його залежності не потрапляли на локальні диски розробників, вони можуть працювати з ним в кодспейсі. В мене як раз така потреба й виникла, та дуже радий, що я можу майже непомітно перестрибнути у хмарне середовище.
Що тут можна сказати. Microsoft не дарма володіє GitHub, VSCode, та Azure!
03.07.2024
Як запобігти вигорянню на роботі
Поступило питання, яким чином я ще не вигорів на роботі. Ну, давайте так: хто сказав, що не вигорів? Пройшов декілька тестів та отримав результати: від малих до помірних ознак вигоряння. Але за самооцінкою я б сказав, що просто життя зараз складне, тому було б дивно, якщо таких ознак не було.
Що мені допомагає?
-
Сон, добра їжа та тренування. Це фундамент всього самопочуття. Що б не було, я стараюся висинатися, їсти здорово та робити хоч щось спортивне. Хоча б довгу прогулянку під подкаст. Якщо в тебе є симптоми вигоряння, раджу почати саме з цієї трійки.
-
Робота, де я маю високий рівень контролю. Як над собою: гнучкий графік, відсутність мікроменеджменту. Так і над продуктом: у нас в культурі висловлювати думку, а не просто “робити, що сказали”. Почуття контролю, гадаю, дуже важливе для запобігання вигорянню. Як то кажуть, за кермом не нудить.
-
Схильність до прокрастинації. Дійсно! Я більше відчуваю хронічне недонавантаження, ніж перенавантаження. Гадаю, це не корелює з реальністю, просто мій психотип схильний так бачити світ. Вигоряння для більш дисциплінованих — моя конячка зайвий вантаж скидає.
-
Ну то й безумовно, підтримка близьких та можливість відверто поділитися турботами та самопочуттям. ❤️
02.07.2024
Правило лісника
Сподіваюся, всім відомо правило скаута: залиш місце чистішим, ніж яким його знайшов. Воно доречне як в лісі, так і в коді. Проте для лісника такого правила недостатньо. Лісник також повинен стежити за загальним порядком та створювати сприятливі умови для відвідувачів.
…Щоб не затягувати з метафорою: в команді лісник — це лід інженер. Та лід інженеру мало зробити задачу та переконатися, що всі лінтери проходять. Окрім того, якщо у виконанні зустрілися очевидні перепони, то їх потрібно усунути — або принаймні внести усунення в план.
Наприклад, якщо виправлення помилки показало, що в цьому місці бракує тестів, то потрібно — не писати всі тести за раз — а принаймні підготувати під них базу. Або трапляться що код потребує системного рефакторингу, а кожна окрема задача ніби недостатньо зачіпляє, щоб його робити. Або документацію потрібно написати. Або оновити фреймворк.
Всі ці задачі критично важливі для продукту, та очікувати що обʼємні зміни будуть зроблені “мимохідь” хибно. Або більше, вимагати цього від всіх інженерів. Якщо кожен інженер буде зупиняти заплановану роботу, щоб провести масивний рефакторинг, то темп розробки стане вкрай непередбачуваним.
На то і є головний інженер, щоб уважно стежити за появленням технічного боргу, та робити життя краще для всієї команди.