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

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

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

18.12.2022

Компроміси баз NoSQL, а особливо Firebase Firestore

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

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

А зараз замислився над тим, як реалізувати вибірку витрат на накопичення у Firebase Firestore. Річ у тому, що структура бази така, що витрати належать до бюджетів, а цілі накопичення існують окремо від них та мають збирати витрати з усіх можливих бюджетів.

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

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

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


17.12.2022

Як додати елементи панелі системного меню за допомогою SwiftBar

🦃🌼🎾 Якщо в тебе Мак та ти вмієш програмувати, варто знати про утиліту SwiftBar. Вона робить можливим додати елементи до панелі системного меню, написав скрипт, що виводить простий текст.

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

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

(Історична довідка: раніше був додаток BitBar, а потім її переписали та назвали xBar, але за моїм досвідом, SwiftBar - ще одна реалізація — стабільніше. Всі вони підтримують той самий формат конфігурації.)


16.12.2022

Автоматизація взаємодії з сайтами

🐰✍️🐰 Інколи доводиться автоматизувати деяку взаємодію з сайтом — або ж, інакше кажучи — доводиться її рутинно робити багато разів, а хочеться автоматизувати. От сьогодні мені довелося відновлювати близько 20 тисяч записів, кожний з яких треба завантажити через вебформу.

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

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

Але якщо треба ще швидше та ще простіше, то у Go найзвичайніший http.Client має можливість зберігати стан сеансу, якщо під’єднати до нього CookieJar. Так я й зробив, бо проєкт на Go. Далі, як вже казав, роблю один запит з імʼям та паролем, щоб авторизуватись, і потім відправляю свої записи.

Цікаво, що вебформа у цьому випадку є фронтендом для внутрішнього API. Тобто все це я роблю замість того, щоб відкрити прямий доступ до того API - це буде і небезпечно, і технічно складніше. А симуляція браузера — хоч і “некрасиве” рішення, але для поодиноких задач — кращий компроміс.


15.12.2022

Поради по вибору механічної клавіатури

⌨️🦾🧈 Пара порад про вибір механічної клавіатури, якщо може ви хочете купити комусь в подарунок, а особливо — собі.

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

Так-от. Як купити клавіатуру, що принесе задоволення? По-перше, переконайтеся, щоб клавіші були зроблені з PBT (а не з ABS). Саме матеріал клавіш визначає то саме тактильне відчуття, та PBT з усіх боків приємніше (хоч і дорожче.)

Далі, не переймайтеся з вибором вимикачів, а для роботи з текстом беріть коричневі, краще якщо Cherry, але не принципово. Коричневі дають чітке відчуття натиснення, та не дуже шумлять (але все одно порядно голосні.)

Ближче всього до клавіатури ноутбука буде розмір 75%. Треба дуже добре подумати перед тим, як брати менше. Більше — то ваша воля, залежно від потреб. До речі, я не помітив проблем з переходом з ноутбука на механіку або зі звиканням. Нормально працюю з обома по черзі.

Раджу заощадити на Bluetooth та взяти клавіатуру з дротом, або ж якщо бездротову, то з радіомодулем. Bluetooth додає затримку, для мене цілком помітну. Також можна на підсвітці заощадити, так легше буде вивчити напамʼять. :)

Нарешті, краще не ганятись за брендами типу Logitech або Razr, бо за моїм досвідом маленькі спеціалізовані компанії роблять краще. Думаю, якщо починати з фільтра PBT + Cherry MX, то результат 100% не розчарує.


14.12.2022

Як працює база Firebase Firestore. Обіцянки про Сінтру

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

Перше, що доведеться зробити — це спланувати базу.

Як я вже писав, Сінтра працює на базі даних Firebase Firestore. Це дуже незвичайна база даних. Вона добре підходить для застосунків, де кожний користувач працює з обмеженим набором даних.

Оскільки Firestore - то і є ваш бекенд, що напряму спілкується з клієнтським кодом, то обмеження доступу забезпечуються безпосередньо в самій базі. Для цього є система правил безпеки. Вони виконують як валідацію, так і авторизацію. Правила не такі гнучкі, як повноцінний бекенд, проте дозволяють, наприклад. перевірити, чи є у користувача підписка. Статус підписки зберігається в іншому записі, а ось цей запис вже редагується тільки зі хмарної функції. Коли все, що не можна довірити клієнтському коду, можна сховати у хмарні функції, то обмеження системи правил прийнятні.

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

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

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


13.12.2022

Опубліковав покращену стрічку для Hacker News

👨‍💻📢🥳 Сьогодні опублікував покращену стрічку для Hacker News, про яку писав у листопаді. Сама стрічка не змінилась — я їй користуюсь вже декілька тижнів і дуже задоволений. Довелося тільки перетворити її на продукт:


12.12.2022

Висновки від розгортування величезної переробки для нашого Redshift

🗄️🛫🌧️ Побачила світло продакшна велике перероблення схеми Redshift, яка тривала понад два місяці. Кілька думок:


11.12.2022

Чому варто частіше писати в підтримку

Сьогоденний пост про підтримку. А саме, про те, що не треба соромитися туди писати.

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

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

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

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

А що порадує підтримку, то це гарно поставлений та деталізований запит, наприклад, так, як радить ставити питання StackOverflow.


10.12.2022

Огляд сервісу Healthchecks.io

Мій проєкт вихідного дня скасувався, тому що читач Руслан звернув увагу на Healthchecks.io. Цей сервіс робить все, що мені потрібно, та є розвиненим та зрілим — рекомендуватиму його своїй команді. Мені тут немає чого додати.

Окрім моніторингу роутера, такий сервіс здатний до інших задач. Можна наглядати за системами, які через міри безпеки (або задля простоти) не мають доступу ззовні — наприклад, сервер фонових задач. І ще одна важлива проблема, для якої в мене досі не було розвʼязку: припустимо, є скрипт, що має працювати періодично (ну може, щоб оновити RSS стрічку). Як дізнатись, що скрипт дійсно працює? А точніше, як помітити, що скрипт припинив працювати? Тепер для цього достатньо додати до кінця скрипту виклик Healthchecks.io.

Потім зʼясував, як працює інтеграція IFTTT з вебхуками. Для цього у них є сервіс Maker. Цей сервіс дає тобі ключ, з яким можна відправляти події на спеціальну адресу https://maker.ifttt.com/trigger/{код події}/json/with/key/{ключ}. Потім за кодом події можна підʼєднати до різних вебхуків різні реакції. Так що мій прототип для Slack успішно переїхав на Healthchecks.io + IFTTT.


09.12.2022

Плани проєкту "зворотній ping" - виділення МVP

📐⚖️🚧 Окреслюю MVP для проєкту “чи є роутер онлайн”, який хочу зробити за вихідні. Та треба памʼятати, що розробка — це тільки половина діла (буквально!), а іншу половину ти маєш витратити на базову інформаційну сторінку та розкрутку.

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

Що ж входить у мій MVP?

Такий MVP має замінити мій прототип з Firebase: замість прямого надсилання у Slack використаю IFTTT.