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

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

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

16.07.2024

Мій досвід резервного копіювання

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

Arq Backup - чудова програма, що вміє робити резервну копію будь-куди — від локального диска до всіх можливих хмарних сховищ. Я почав користування з власного NAS, а пізніше переїхав на AWS S3, а потім — на Google Drive. З цієї історії можна зробити два висновки. Так, це дійсно дуже круто, коли ти можеш обрати, де зберігати резервну копію: за ціною, географією, лояльністю до бренду. Але: з такою програмою будь готовим адмініструвати місце призначення та піклуватись про нього.

З негативного: Arq Backup зберігає локальний індекс сховища (якщо вірно згадую), та згодом цей індекс стає великим. Тут ще треба дивитися на характер резервного копіювання: я люблю зберігати практично весь зміст диска, окрім очевидно непотрібних. Можна заощадити не тільки на місці, а й на системних ресурсах, якщо обмежитися важливими файлами.

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

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


15.07.2024

Генерація кольорів для CSS у 2024

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

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

Проте RGB - не єдина модель кольорів, та сучасний CSS підтримує інші. Модель — це спосіб задання кольору через координати. Наступна за підтримкою — модель HSL, її підтримують 99% браузерів. Для нас важливо, що в HSL можна зафіксувати яскравість та насиченість, а змінювати відтінок. Таким чином генерація сумісних кольорів стає майже тривіальною:

`hsl(${(i * 360) / count} 50% 50%)`;

Або, якщо хочемо, щоб, наприклад, аватар користувача був завжди одного кольору, можна взяти решту від ділення ідентифікатора на 360, або хеш чогось. (До речі, 360 тут — це кількість градусів у колі.)

Ще є модель LCH/Lab - вона ще краще, бо в HSL яскравість не завжди відповідає сприйняттю. Але LCH підтримують тільки 91% браузерів. Плюс, за моїми перевірками, для такого завдання різниця невелика.


14.07.2024

Технічні проблеми з іграми на macOS

Я тимчасово відірваний від свого ігрового компʼютера (навіть Parsec не допоможе, бо він просто вимкнений.) Залишається в щось пограти на макбуці. Але, навіть коли він включений у монітор, клавіатуру та мишу, геймінг з маком залишається чимсь особливим… щоб його любити, доводиться йти на компроміси.


13.07.2024

Емулятор відповідей SMTP

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

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

Тому ми вбудували у Mailtrap емулятор відповідей. Достатньо надіслати листа, наприклад, на bounce+555+spam@inbox.mailtrap.io, та система відповість: 555 spam. Звісно, це працює навіть для користувацьких клієнтів, таких, як GMail - до речі, цікаво було подивитися, як він реагує на тимчасові помилки (тобто з кодами 4xx).

Зміст відповіді додається до адреси отримувача з URL-кодуванням. Чому обрали саме адресу? Бо це працює не тільки в будь-якому клієнті, а й навіть тоді, коли ти не контролюєш зміст листа (наприклад, тих листів, що надсилаються застосунком.) Адреса отримувача - найгнучкіший з усіх доступних носіїв.

Але, це змушує нас кодувати зміст (який може бути довільним рядком ASCII) в набір символів, доступний в імені скрині електронної пошти. Обрали кодування URL, бо воно залишає зміст читабельним. Нюанс: за стандартом поштові адреси зводяться до нижнього регістру, тому якщо у відповіді потрібні великі літери, їх також доведеться закодувати: Spam стане %53pam. На жаль, стандартні кодувальники цього не зроблять, хоча механізм кодування URL не забороняє будь-який символ замінити на його код. В майбутньому щось для цього придумаємо.

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


12.07.2024

Хліб

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

Для мене домашній хліб почався з подорожі в Австрію, де я скуштував дуже простий житній хліб на заквасці. У нас такого практично не купиш; або суміш з пшеницею, або щось солодке. Знайшов рецепт. Сподобалось.

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

Наразі я печу хліб з цілозернової спельти. Рецепт тут. Спельта в нас почалася як “здорова альтернатива пшениці”, але як виявилось, вона просто смачна: духмяніша за пшеницю, легша в роботі ніж жито (яке сходить ну дуже важко.) Поки нічого кращого не треба.

Нарешті, можу порадити книгу Ібана Ярса “Домашній хліб”. Мені сподобалось, що рецепті в ній “відкриті”, а техніки добре проілюстровані. Також автор пояснює, як правильно використовувати дріжджі. Гарний посібник.


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 вийшло не тільки чіткіше, але ще й швидше. Та цей цифровий план легше буде використовувати повторно. Pixelmator 1 : папір 0.