Стендап Сьогодні
Що я зробив, що я хочу зробити, і що це все значить.
Повсякденні здобутки в форматі стендапу.
Детальніше в статті
Підписатись на RSS
📢
Канал в Telegram @stendap_sogodni
🦣
@stendap_sogodni@shevtsov.me в Федиверсі
06.02.2023
Як працюють платежі в додатках з Apple App Store
Епловська система платежів працює зовсім не так, як я звик. А до чого я звик? Практично всі платіжні системи, з якими я стикався, працюють за принципом вебхука на довірену адресу нашого сервера. Тобто, спочатку покупець виконує платіж, а потім нам приходить квитанція, яку треба обробити, та надати сплачену послугу. Якщо йдеться про підписку, то потім платіжна система надсилатимете квитанцію регулярно. Таким чином, від нас залишається тільки оновляти статус підписки при отриманні вебхука.
Але в Apple ніякого вебхуку немає. Напевно, це повʼязано з тим, що серверна частина не обовʼязкова для мобільного додатка. Замість того, це ми маємо питати у сервісу покупок, чи не змінився статус підписки. Для цього під час покупки отримуємо довжелезну квитанцію з підписом. Її маємо зберегти в базу, а потім періодично перевіряти. Як часто — вирішувати нам. Ясно, що статус зміниться тільки якщо черговий платіж не пройшов, або якщо користувач скасував підписку. Але щоб не помилитись, просто перевіряємо статус щодня — поки квитанцій кілька десятків, це підходить.
Власне, зачепив цю тему тому, що епловський сервіс перевірки платежів регулярно та ганебно повертає помилку 502. Поки спробую вирішити повторними спробами. Взагалі це не єдина проблема з In-App Purchases. Головна проблема — що IAP це єдиний дозволений спосіб брати гроші з додатка на iOS. Але навіть якщо головний сервіс ми надаємо з сайту (я про Сінтру, до речі), а додаток сам по собі не працює повноцінно, то все одно примусово мали додати підтримку IAP. Причому спочатку коли додали підписки з сайту, то Епл нічого не сказав. Але через кілька місяців, при випуску чергової версії додатка, раптом відмовили через відсутність IAP. Та після цього в нас не залишилось вибору — тільки додати підписку через Епл, або ніколи не випускати оновлення. Так і вийшло, що в нашому мінімальному додатку до вебсервісу все одно є можливість підписки.
До речі, технічних проблем з тим, щоб платити за вебсервіс підпискою з мобільного додатку, немає; під час оформлення підписка привʼязується до вашого рахунку, та рахунок отримує один та той самий статус активної підписки, незалежно від способу оплати.
05.02.2023
Відображення змін файлів з PRу з GitHub
Продовжуються мої експерименти з інтерфейсом для перегляду повідомлень для GitHub. Здобув всі необхідні дані, залишилось зробити базовий інтерфейс та цього буде достатньо.
Складнощі виникли з переглядом змінених файлів. Весь PR можна забрати з API у вигляді diff-файлу - для цього треба зробити запит з заголовком Accept: application/vnd.github.diff
. Це розповсюджений формат, який легко показати з підсвіткою, наприклад, бібліотекою Prism. Але ж просто показати зміни недостатньо. Для мене необхідно додавати коментарі на окремі змінені рядки — без цього ніякого огляду PRу не вийде. Тому знайшов інший підхід — бібліотеку gitdiff-parser, яка розбирає Diff-файл на файли, фрагменти, та рядки. Далі залишається їх тільки відобразити.
Може виникнути логічне питання — а як сам GitHub відображає сторінку змінених файлів, та чи можна підгледіти там якесь більш зручне API. Але ні, бо на моє розуміння, GitHub використовує Server-Side Rendering, та повертає вже готовий код сторінки. Попри це, як на мене, сторінки PR працюють з неприємними затримками. Саме тому я думаю, що зможу зробити додаток, що буде приємніше, хоч і з меншим набором функцій. Також, навпаки, можна додати такі можливості, за якими зараз доводиться ходити на інші сторінки — наприклад, хотів би бачити blame для змінених рядків, тобто коли та хто їх змінював перед поточним PRом.
Дізнався про обмеження запитів до API GitHub з персональним токеном. А саме, це 5000 запитів на годину. Тобто можна зробити відразу багато — це добре — але потім доведеться довго чекати. Обмеження щедре, та я його знайшов тільки через багаторазове перезавантаження свого додатка, хоч він стягує по декілька різних запитів на кожне з моїх поточних 75 повідомлень. Але, мабуть, краще впровадити якийсь кеш — напевно, у LocalStorage.
04.02.2023
RSS-стрічка для новин про війну з Реддіту
📢 Сьогодні нарешті публікую RSS-стрічку з Реддіту, яка збирає пости з сабреддітів про російсько-українську війну. Перелік сабреддітів курується мною, тому там є шановний /r/NCD
, в якому проміж грубих жартів публікується як не найкмітливіша аналітика в інтернеті. Колись зроблю й інші стрічки, але почав з головної теми.
З попереднього посту про цю стрічку помінялось небагато. Для того, щоб збирати пости з багатьох сабреддітів, створив мультіреддіт — це вбудований засіб агрегації. Також виявив, що власний RSS реддіту взагалі немає сенсу парсити, коли є формат JSON. А далі — пости з мультіреддіту проходять по тому самому алгоритму, що я вже зробив для Hacker News.
Хотів, щоб мультіреддіт не світився в моєму акаунті; але якщо зробити його приватним, то я не зможу витягувати стрічку без авторизації. Тому звернувся до типового для реддіту механізму — створив анонімний акаунт, який і володіє публічним мультіреддітом, та ніяк зі мною не повʼязаний. (Потім випадково забув не тільки пароль, але імʼя користувача, а також адресу електронної пошти — бо вона була прихована через сервіс Hide My Email. На щастя, приховану адресу можна знайти у системних налаштуваннях iCloud, а за нею відновити все інше.)
03.02.2023
Поради як тримати Terraform в простоті
Terraform, хоч і є декларативною мовою програмування, але все ж таки вміє робити чимало функціональних перетворень над даними. Деякі дуже корисні - formatlist допоможе переформатувати рядки за шаблоном, та я часто їй користуюсь — наприклад, щоб перетворити IP на маски мережі командою formatlist("%s/32", local.ips)
. Повноцінного програмування все одно не вийде, але можна написати досить складні перетворення. (Варто памʼятати, що замість звичної функції map
списки відображаються командою for
. )
Так я колись витратив пару днів, щоб генерувати правильну розбивку IP адрес за мережами та машинами. По-перше, це зайняло купу часу. По-друге — як тільки зʼявилися додаткові вимоги, адаптувати код не вийшло. Тому що, по-третє — хоча я намагався наповнити код коментарями, все одно було забув, як воно працює, а головне — чому. Як ілюстрацію пропоную подивитись функцію matchkeys - таку езотерику я в повноцінних мовах не бачив.
Тому моя поточна думка — що краще було б вручну задати на прості вихідні дані, а розгорнутий кінцевий результат перетворень. Так, доведеться більше робити вручну. Але головне, що ця конфігурація буде більше схожа на топологію самих ресурсів, а значить, буде легше зʼясувати, що до чого. Що, на мою думку, краще, ніж коли конфігурація проста, але як з неї створюються ресурси — абсолютно незрозуміло. До того ж конфігурацію можна генерувати не вручну, а скриптом, та передавати у форматі JSON.
А ще, в усіх можливих випадках, раджу адресувати повторювані ресурси ключами, а не індексами. Тобто замість метааргументу count
вживати for_each.
02.02.2023
Пост симпатій до бази даних Redis
Пост симпатій до бази даних Redis. Всі знають, як використати Redis у якості кеша. Колись давно цю задачу виконував memcached (який ще досі живий!), але зараз всюди, де я знаю, роль кешу зайняв Redis. Та, без заперечення, цю роль він грає чудово. Але Redis вміє набагато більше. Оскільки Redis тримає всі дані в оперативній памʼяті, правильно буде думати про нього не як базу даних, а як зовнішню оперативну памʼять вашого додатка.
Тому Redis ідеально підходить для даних, потрібних в реальному часі. Лічильники, передача повідомлень, таке інше. Порівняно з внутрішньою памʼяттю, Redis буде доступним з різних машин та збереже дані навіть при перезапуску додатка, а також і при перезапуску сервера Redis теж — хоча гарантії надійності тут слабкі, тож для довготривалого збереження краще обрати справжню базу даних.
Насправді у Redis є сила-силенна команд, які уможливлюють складніші обчислення саме на сервері. Наприклад, мені колись довелось використати команди для роботи над бітовими рядками. Цінним є те, що у кожної команди зазначена її обчислювальна складність, тобто можна напевно розрахувати швидкодію майбутнього рішення. Тож, якщо у вас є додаток, скажімо, на Ruby, та потрібно прискорити якийсь алгоритм, то можливо, Redis та його розширені команди — це все, що потрібно. А далі можна навіть перенести алгоритм прямо у Redis, бо він підтримує скрипти на Lua… По цьому шляху я теж пройшов, але нарешті вирішив переписати все на Go - проте прототип вийшов чудовий.
01.02.2023
Як переконатись, що архітектура витримає? Йти від зворотного.
Продовжуючи тему про стрес-тести — як все ж таки переконатись, що архітектура витримає навантаження, якого у вас зараз немає навіть близько? Я пропоную виходити зі зворотного. Чого ваша архітектура не витримає? На мою думку, це питання менш абстрактне, та тому з ним легше впоратись — та навіть перевірити.
Багато де межі дійсно немає — наприклад, при можливості лінійного масштабування, це просто питання грошей. Тут епоха хмарної архітектури відкрила для нас суцільно нові проєкти, бо до появи AWS та іншого масштабування закінчувалось на одній або декількох машинах, а далі — вже зовсім інші витрати. Також є глобальні хмарні сервіси, такі як AWS Kinesis Firehose, які мають абсолютно космічні межі використання, тому на них можна впевнено покластися (теж за гроші, звісно.)
Інколи рішення працює для будь-яких обсягів, але впирається в фізичну межу. Так, база даних зі зберіганням у памʼяті (Redis) чудово працюватиме, поки влазить в памʼять однієї машини. Проте памʼять машини — це вже не 640Kb з відомої цитати Біла Ґейтса, а, у випадку AWS ElastiCache, до 640 ГІГАбайт. Тож влізти може багато.
Та, нарешті, є багато підходів, які масштабуватись не будуть, а працюють зараз тільки через низький обсяг клієнтів (або ж взагалі до появи справжніх клієнтів.) Наприклад, якщо ми свідомо знаємо, що складність обробки зростає як квадрат кількості користувачів. Так, з 10 тестовими користувачами все працює добре — але ж на 10 тисяч ми ніяк не вийдемо. Сучасні програмісти рідко пишуть щось складне, але ось накоїти проблем в базі даних — це ми можемо.
Коротше, чесному інженеру на відкрите питання “чи все буде добре” відповідати складно. Краще перетворити його на “що піде паскудно”.
31.01.2023
Перший місяць користування блокнотом для самоменеджменту
Вже цілий місяць я веду свої справи по блокноту. Не кинув поки! Що стало несподіваною перевагою — блокнот дуже добре ізолює увагу. Порівняно з телефоном або ноутбуком, коли працюєш з блокнотом, то немає на що відвернутися. Бо, мабуть, у всіх бувало так, що взяв в телефон у руки — а через пʼять хвилин вже згадуєш, для чого. Тому щоранку я роблю каву та сідаю за блокнот писати справи на день, а потім вже лізу в інтернет. А якщо все добре, то щовечора перед сном також записую все, що крутиться в голові. Така собі медитація на блокнот виходить.
Як на мене, то у самоорганізації є етапи. На початку в голові є декілька гострих, важливих задач, заради яких зазвичай і починають щось записувати. Коли з гострими задачами закінчено, раптом виявляється, що в тебе купа ідей, які припинили бути репресованими теми гострими, і також хочуть бути записаними та зробленими. На цьому етапі в мене ідеї просто фонтанують десятками. Далі, третій етап — все, що записано, вже неможливо зробити ані сьогодні, ані завтра; тут зʼявляється список проєктів та набирає чинності якесь розставляння пріоритетів. (Я зараз тут.) А після того, як здобуваєш певну кількість результатів, стає питання вищого порядку: навіщо все це, і куди я рухаюсь? Тут вже треба розбиратись з довгостроковими цілями, а також зонами відповідальності. На цьому моє розуміння поки закінчується.
30.01.2023
Порада про захист сайтів з Cloudflare, та інша порада про цінність вузько націленого коду.
-
Якщо використовуєте Cloudflare, моя порада — встановити у правилах сторінок високий рівень безпеки для вашої сторінки логіну (а також, можливо, реєстрації та білінгу, залежить.) Це у
Page rules -> додати -> Security Level: High
. До такого висновку я прийшов після того, як припинив чергову атаку по підбору паролів на нашому сайті. А ще цікаво, що наш нападник, який мав доступ до тисячі IP-адрес, не здогадався міняти свій User Agent, і таким чином був легко відфільтрований та знешкоджений. Добре, що Cloudflare дає всі інструменти, щоб відділити злочинні запити від нормальних, та швиденько їх заблокувати. Погано, що я поки не знайшов способу автоматично помічати такі атаки раніше. Цього разу помітив через високе споживання процесора, але це трапилось суттєво пізніше початку атаки. -
Всі інженери полюбляють узагальнені, універсальні рішення. Так приємно знати, що ти готовий до будь-чого. Але треба признати, що універсальність часто отримується в обмін на швидкодію. Іноді найкраща оптимізація — це прописати код чітко під задачу. Так в мене і трапилось: шукав шляхи оптимізації величезної SQL-вьюхи на будь-який випадок життя. А потім зрозумів, що насправді треба виписати найбільш популярні структури запитів, та зробити для них окремі, спрощені вьюхи. До речі, оскільки все це керується будівельником запитів на Ruby, то клієнти навіть не дізнаються, що від обраних аргументів міняється повністю весь запит. Так з єдиним інтерфейсом продовжуватимуть працювати як прискорені популярні запити, так і універсальні, але повільні.
29.01.2023
OpenMW: сучасний спосіб пограти у Morrowind. А також, його збірка — спосіб себе помучити.
Morrowind, на мою думку — вершина RPG-пісочниць від першого лиця. Немає у наш час більше великобюджетних ігор з левітацією (бо швидкодія), з такою кількістю діалогів (бо озвучка), та й з таким дивним, незвичним світом (бо не окупиться.) Так що, хоч грі вже понад 20 років, а спільнота досі жива та є що від неї чекати.
Сучасний спосіб грати у Morrowind - це через клієнта OpenMW; він повністю заміняє оригінальну програму, та не тільки підтримує весь функціонал, а й додає купу нового. Чого варто хоча б підтримка macOS!
Для керування модами є сучасний менеджер модів portmod. А для пошуку модів, окрім сайту NexusMods, що колись називався TES Nexus, є ще й сучасний ресурс Modding OpenMW, де зручно перелічені різні набори модів — від тих, що роблять косметичний ремонт оригінальної гри, до повних перетворень. (До речі, portmod
вміє встановлювати списки модів з цього сайту.) Також наприкінці минулого року вийшли величезні доповнення карти та квестів від Tamriel Rebuilt та Skyrim: Home of the Nords.
Одним словом, для мене Morrowind залишається чудовою розвагою, яку можна запустити на ноутбуці для короткої перерви. Так воно й було, поки не захотілось більшого. Побачив, що у їхньої команди немає кому зробити збірку останньої тестової версії для M1 Mac; стабільна версія є тільки для Intel, а попередня тестова версія для M1 працює в рази краще, але вона з багами.
Що ж, я щось вмію, вирішив зробити збірку сам. Основний набутий досвід — тулчейни для веброзробників це просто космос, порівняно з тим, з чим працюють розробники на C++. Керування залежностями як таке відсутнє; залежності “просто” мають бути присутніми на твоїй машині. Щось з них може встановити Homebrew; щось потрібно стягнути та зібрати вручну. Але стандартів бібліотек як таких теж немає; буває так, що встановлена з Homebrew версія має іншу структуру та не підходить для скрипту збірки (так сталося з bullet). До речі, всі бібліотеки, які довелося збирати, використовують утиліту CMake. Кожний скрипт CMake має секцію, де він намагається вгадати, чи є на диску його залежності, та де, та в якому форматі. Інколи бібліотек є декілька, та він плутає. Інколи замість бібліотеки на M1 бере бібліотеку для Intel. Інколи він спочатку знаходить, а потім під час компіляції каже дивну помилку, причому у 100% випадків якщо щось не компілюється — то проблема з залежностями. Якщо тільки не з компілятором. Бо на різних системах все компілюється різними компіляторами, а MacOS - не сама популярна OS, та до того ж, з не дуже стабільним тулчейном.
Поки в мене вийшло зібрати додаток OpenMW, але в ньому чомусь бракує динамічних бібліотек, тому він не запускається. Спробую наступного разу, як буду сердитися на Yarn.
28.01.2023
Як працюють віджети на iOS
Вже два роки на iOS є віджети, та, напевно, всі вже звикли до цих зручних доповнень до звичайного інтерфейсу додатків. Але з боку розробки віджети стали революцією. Будь-який розробник додатків для iOS добре знає, що вся архітектура цієї операційної системи побудована на економії батареї, а значить — процесорного часу. Тільки поточний додаток отримує повний доступ до процесора; всі інші — тільки суттєво обмежений; фактично, вони стоять на паузі, якщо не отримують повідомлень та не відтворюють звук. До того ж додаток, прихований з екрана, має бути готовий, що ОС повністю завершить його роботу будь-який момент. Як же ж при такій суворій економії енергії можливо, щоб відразу декілька віджетів були постійно відображені на головному екрані?
Відповідь в тому, що віджети на iOS взагалі не є додатками. Правильніше скати, що віджет являє собою векторне зображення, тобто інструкцію про те, що треба намалювати. Технічно, є також програма, яка будує віджет, але вона викликається відносно рідко — в кращому випадку, декілька десятків разів на день. Тож віджети за своєю природою не можуть мати нічого інтерактивного, окрім кнопок-посилань. Для економії оновлень, віджет насправді задається як така собі анімація, тобто не одне, а серія зображень, які змінюються за зазначеним розкладом. Наприклад, віджет погоди може завантажити послідовність погодних станів на кожну з наступних годин по черзі. Чого він не може зробити, це щогодини ходити на сервер за новими даними. Принаймні, не гарантовано.
Така система розрахована на те, що ми можемо передбачити зміст віджета, поки додаток не змінюється. Та дійсно, за моїм досвідом, такий прогноз можливо та навіть цікаво робити. Наприклад, мій віджет для самоменеджменту враховував поточний таймбокс (наприклад, робота / дім), та показував відповідну наступну задачу. Для цього в додатку я будував серію станів для кожного таймбоксу. Така серія була актуальна, допоки ти не зайдеш у додаток — наприклад, щоб закрити задачу. Тоді віджет перемальовувався.
А ще цікаво, що структура віджета — це, фактично та буквально, SwiftUI. Як бачите, коли Apple робили декларативну бібліотеку для інтерфейсів, вони планували не просто спростити розробку та зробити її схожою на React. Вони також заклали можливість зберігати та відтворювати знімки інтерфейсу. Це корисно не тільки для віджетів, але й для Apple Watch, де економія батареї ще більш важлива.