RSS
Поиск
16.11.2023


Ах да, ну и кешбэк уж точно лучше любых программ лояльности отдельных сетей, которые предлагают возврат 0,5-2% от покупки какими-то своими бонусами, которые потратить можно только у них. Так ещё и при этом некоторые не дружат с агрегаторами и требуют установки собственных отдельных приложений, чтобы либо списывать баллы ░░░, либо даже начислять ░░░. Как владелец телефона с 32 Гб постоянной памяти, я максимально негодую! Удобно сделано во ВкусВилле, что можно привязать чек к карте уже после покупки, но почему-то больше нигде такого не видел. Причём мода на собственные приложения дошла и до сетей фастфуда, из-за чего теперь можно легко забить несколько гигабайт свободного места на смартфоне бесполезным мусором. Спрашивается, а оно надо? Может проще не париться об этих баллах и жить счастливо? Хотя есть скидочные программы, где использование карт доведено до апогея абсурда, когда тебе без карты предлагают максимально завышенную стоимость… ░░░
16.11.2023


16.11.2023


Кешбэк Ну а остаток поста посвящу известному инструменту, широко популяризованному банком Тинькофф. Когда-то они совершили революцию, сократив свою маржу с комиссий за платёж и поделившись частью дохода с клиентами. До них, по сути, из широко известных банков были только Спасибо от Сбербанка, но не по шикарным для дополнительной карты условиям СберКарты, о которых мы поговорим позже, а с уровнями лояльности, для которых установлена заградительная куча условий, проёб которых лишает дополнительного дохода на следующие три месяца, что, конечно же, лютый пиздец по современным меркам. А Тинькофф начал возвращать по 1% от всех платежей настоящими рублями, дав по трём категориям аж 5%, которые превышают ставку интерчейнджа, так что за них банк доплачивает из своих средств! Но с тех пор прошло много лет, почти везде сменились владельцы, топ-менеджеры, и ситуация сильно поменялась. Теперь почти везде дают какой-либо приличный кешбэк. Даже экосистема Сбера разрослась настолько, что СберСпасибо перестали быть бесполезными и теперь их можно спокойно тратить в Самокате (для больших городов) или МегаМаркете (для провинции). Все предложения охватить сложно, поэтому я расскажу, какими пользуюсь лично сам. Многие считают кешбэк мелочью, а раздумия о нём крахоборством, но за 4 года использования со всех карт у меня вышло более 100 тысяч выгоды, так что не такое уж это и бессмысленное занятие. Кредитная карта Тинькофф ALL Airlines Кешбэк дают милями, но 2% с каждой покупки, без дополнительных категорий. С шести тысяч миль можно списывать их на авиабилеты 1 к 1, но также можно их использовать для покупки билетов в театр и кино, на концерты, а также на продукты во ВкусВилле (правда, скидка по любимому продукту не учитывается, хоть карту и можно привязать) через раздел «Город» в супераппе банка, правда, по курсу 1 ₽ = 1,25 мили, что выходит всё равно выгоднее стандартного 1% по дебето́вой карте (особенно если учесть, что тратишь не свои деньги, и на них капают ещё проценты на остаток/по накопительному счёту). Дебетовая карта Альфа Банка В прошлом Альфа Банк очень любил выдумывать условия со звёздочками, предлагая на первый взгляд очень выгодные условия, но на деле оказывающиеся сильно приукрашенными. В последнее время за ними такое я уже не замечал, а условия и качество приложения в целом стали близки конкурентам: те же 4 категории на выбор + случайный суперкешбэк и бонусная категория за совершение выбора до конца предыдущего месяца. При этом часто попадаются очень выгодные категории типа супермаркетов, в отличие от того что предлагает Тинькофф. В том числе хорошая категория может выпасть и два месяца подряд. Однако в долгосроке я бы не стал на это полагаться, конечно) Дебетовая карта МТС Банка — CASHBACK МИР Интересна наличием текущей акции: 5% за супермаркеты до 31 января 2024 года. Однако кешбэк выплачивается внутренними бонусами, которые можно потратить в общем-то только на связь, билеты на мероприятия или другие траты внутри экосистемы. Дебетовая СберКарта Интересна 5% на кафе и рестораны. Причём один из немногих банков, который не выделяет фастфуд в отдельную категорию, что является одной из главных наёбок программ кешбэка. Кешбэк приходит бонусами, но, как говорилось выше, теперь их легко можно потратить в широкой экосистеме Сбера. Правда надо держать на карте от 40 тысяч или тратить от 20 в месяц, чтобы получить эту категорию.
16.11.2023


Сегодня немного отвлечёмся от айтишной тематики и поговорим о смежной области — о финансах. Нет, не о зарплатах обнаглевших и зажравшихся программистов, а о банковских продуктах и эффективном использовании кровно заработанных. Вообще я планировал расписать возможности всех инструментов, от кешбэка до инвестиций в ценные бумаги, золото и крипту, но понял, что на самом деле мне едва ли есть, что добавить к огромной куче материала, которую уже подготовили брокеры. Особенно в текущей геополитической ситуации. Проговорю лишь очевидную, но самую важную вещь: главное в накоплениях — это управлять рисками и минимизировать их, диверсифицировать капитал, что бы ни ни один трейдер, ни один бандит или мошенник, ни одно государство не могло отобрать сразу всё. Поэтому стоит в той или иной степени, в разных пропорциях, но инвестировать сразу во всё: валюта, банковские вклады, недвижимость, облигации, портфель акций, диверсифицированный по странам, брокерам и депозитариям, криптовалюты. Каждый инструмент надо изучить, чтобы не нарваться на скам, но всё равно никто не может предвидеть все возможные риски, как мы наглядно видим по последним событиям. Только инвестирование понемногу во всё может дать хоть какие-то гарантии. Ну а начать стоит с создания финансовой подушки из накопительных счетов и банковских вкладов, затем построить лестницу облигаций, после чего уже можно начинать инвестировать в БПИФы и осторожно покупать акции или золото. Стоит следить за балансом портфеля по отраслям, валютам и странам, чтобы не было сильных перекосов. Однако сейчас всё вообще стало сильно сложнее: из всех иностранных акций надо выходить до конца января (если дадут ещё), на российском рынке торгуют одни физлица, что тоже не внушает доверия. Похоже, пора реально брать льготную ипотеку и инвестировать в бетон… ░░░
13.11.2023


Посмотрел прошлогодний доклад про виртуальные треды в новой Джаве. В целом, первая половина видоса малоинформативна для людей, знакомых с обычной многопоточкой, корутинами в Котлине и понимают, что такое CPS. А вот дальше уже идёт разговор о проекте Loom и виртуальных потоках, появившихся в Java 19. По сути в Джаве появляется возможность использовать обычный синтаксис создания потоков или экзекуторов, но при котором создаются не системные потоки с собственным стеком, а специальные "зелёные" потоки, стеки которых размещаются в хипе и которые раскидываются по системным потокам, число которых обычно равно числу ядер процессора, специальным планировщиком рантайма. Причём под них массово переписывается стандартная библиотека, добавляя кучу новых возможностей. Плюсы: 1️⃣ не требуется специальный синтаксис и магия компилятора, от которой страдает инлайнинг и прочие оптимизации кода, для преобразования асинхронных функций; 2️⃣ появляется возможность использования блокирующих методов стандартной библиотеки без создания реальных блокировок; 3️⃣ рантайм может выделять дополнительные системные потоки под задачи, которые нельзя выполнить асинхронно, но которые могут подвесить текущий поток. Ограничения: 1️⃣ хоть стек обычно и копируется из хипа и обратно не полностью при переключении задач, в определённых случаях можно больно попасть на разворачивание и полное копирование стека; 2️⃣ не стоит запускать на грин тредах числодробилки) 3️⃣ нельзя интеропиться с нативным кодом; 4️⃣ в качестве планировщика используется несменяемый ForkJoinPool, который не идеален под эту задачу, агрессивно воруя задачи и вызывая постоянные cache miss'ы. Возможно, что-то за год уже поменялось. Если кто в курсе, то напишите в комментариях)
10.11.2023


Уровни изоляции транзакций в реляционных СУБД Классический вопрос из собеседования на бэкенд-разработчика, который, по-моему, слишком часто объясняется очень сложно и невнятно. Как это обычно выглядит: после объяснения транзакций в общем тебе вываливают список возможных аномалий, список уровней изоляции, составляют табличку, какие аномалии на каком уровне фиксятся — и всё, живи с этим. Никаких практических примеров, никакой конкретики, только какая-то каша из заумных слов по лучшим стандартам университетской манеры подачи материала. Особенно тяжёлым может оказаться осознание разницы между read committed, repeatable read и phantom read, если они объясняются похожими словами и формулировками без отдельного фокусирования внимания на отличиях. Я всё-таки нашёл пару нормальных видосов: краткое объяснение и наконец-то практическое — а лучше вообще потыкать просто разные уровни, отправляя транзакции вручную из двух параллельно открытых терминалов. Но всё-таки попробую сформулировать суть простыми словами: Параллельная запись (lost update) запрещена на любом уровне изоляции. Отличие только в чтении. Так что только если в рамках транзакции выполняется несколько селектов, имеет смысл подумать, устраивает ли вас уровень по умолчанию, установленный в СУБД (для PostgreSQL и Oracle это Read Committed, для MySQL — Repeatable Read). ➖Read uncommitted — никакой изоляции по чтению, позволяет видеть изменения, которые другие транзакции ещё не закоммитили и которые могут быть отменены (что, разумеется, совсем плохо, и на такие данные, как правило, нельзя полагаться). ➖Read committed — видны только закоммиченные изменения, но при этом два селекта могут дать разный результат (unrepeatable read). ➖Repeatable read — обновление данных в других транзакциях не будет влиять на селекты в этой, однако параллельно выполняющиеся вставки всё ещё могут давать новые строки в последующих селектах. ➖Serializable — полностью последовательное выполнение транзакций с максимальным уровнем блокировок. Unrepeatable read и phantom read отличаются только тем, что первый про UPDATE'ы, а второй про INSERT'ы, но при этом решают их разные уровни изоляции. Вот и всё! Достаточно просто, не так ли? И даже без табличек!
09.11.2023


Дальше добавлю немного общей информации в отрыве от проекта. Какие ещё могут быть индексы? Частичные. Можно с помощью конструкции WHERE ограничить записи, по которым будет строиться индекс, чтобы не включать туда, например, NULLы или уже обработанные заказы с соответствующим статусом. Из других типов индексов, кроме B-Tree, могут быть полезны разве что GIN/GiST (второй чуть быстрее для записи, но медленнее для чтения, так что используется реже). Они используются для полнотекстового поиска и работы с JSON/JSONB. Индекс hash, который поддерживает только операции сравнения, выигрывает у B-дерева только по используемому дисковому пространству и сейчас уже не особо актуален. Ну а всякие специфичные индексы для работы с координатами и используемые в геоинформационных системах не вижу смысла рассматривать. Можно ли использовать UUID в качестве первичного ключа? В принципе да, если это специальный тип, который в два раза меньше строки, и при использовании time based UUID v7, который не будет нарушать правило упорядоченности индекса и приводить к постоянным перестройкам. А ещё, если у вас есть операции удаления и проверки по внешним ключам, не забывайте вешать индексы на FK! При написании материала была использована информация из следующих докладов: ➖ Владимир Ситников — B-tree индексы в базах данных на примере PostgreSQL ➖ Андрей Сальников — Индексы в PostgreSQL. Как понять, что создавать
09.11.2023


При проектировании БД для бота столкнулся с интересным моментом: у нас есть две основные команды — /top и /grow. Первая производит выборку и сортировку по всем игрокам в чате, вторая отбирает и увеличивает значение конкретной записи. Логика и наблюдение за поведением пользователей подсказывают, что /grow вызывается значительно чаще, так как его вызывает каждый пользователь, а вот топ, полученный одним, видят все. Получается, что операции записи будут превалировать над операциями чтения. Да, точно сказать невозможно, ибо будут и холостые повторные нажатия /grow, приводящие только к чтению, но всё равно распределение получается далёким от эталонного для реляционных СУБД — 80-90% чтений на 10-20% операций записи. Нужен ли нам здесь индекс? Как мы знаем из лимитов Telegram, на одну супергруппу у нас может быть максимум 200 тысяч человек. Правда одновременно, ведь они могут входить и выходить, так что на самом деле больше. Но если посмотреть на глобальный рейтинг чатов, то можно сделать вывод, что все подобные чаты — это какие-то доски объявлений, рекламные помойки, накрученный бизнес и прочий скам, не входящий в нашу ЦА. Так что едва ли стоит рассчитывать на более чем 100 000 записей на чат даже в теории. Что, в принципе, вроде как не много, особенно учитывая, что среднее число записей вряд ли будет больше нескольких сотен. Но при этом индексы сильно замедляют операции записи. На сколько? DBA в докладах говорят, что в среднем можно считать, что один индекс замедляет запись в три раза. Давайте вкратце вспомним, как работает повсеместно используемый B-Tree. Это довольно низкое (3-4 уровня), но очень широкое отсортированное дерево, где узлы связаны как вертикально, так и горизонтально (с помощью двусвязного списка). В принципе, при обновлении одного значения нам не нужно перестраивать весь индекс: достаточно провести ребалансировку нескольких веток (удаление записей, кстати, вообще не влияет на индекс до вакуума или выборки). Мне кажется, оценка деградации в три раза для данного случая будет излишне пессимистичной, но в итоге все теоретические рассуждения заходят в тупик, ведь получить точный и окончательный ответ можно будет только при реальной эксплуатации и на реальных данных 😅 Выбраться из замкнутого пучка мыслей «Как же сделать изначально?!» помогает дальнейшее пожелание пользователей сразу же видеть их текущее положение в топе при вызове команды /grow, которое приводит к дополнительной выборке и восстановлению доминирования операций чтения, что позволяет обосновать расширение индекса с (chat_id) до (chat_id, length DESC). Да, мы тут можем сразу указать обратную сортировку от большего к меньшему, чтобы выборка была эффективнее. Стоит ещё отметить, что составной индекс можно грубо представить в виде склейки значений двух строк, в указанном порядке. Поэтому он может использоваться как в выборке по двум полям, так и только по первому, но никак не по второму. Ну и первым полем стоит делать наиболее селективное, которое отрежет максимальное число нерелевантных строк. (продолжение ниже)
07.11.2023


Так что же за новый проект? Ну вот и пришло время раскрыть карты про нового бота. В этот раз он будет выполнять не какую-то маленькую полезную функцию, а предоставлять игровые механики и по сути быть некоторым аналогом тамагочи. В принципе, есть уже много подобных аналогов на разных языках и под разные аудитории, возможно, вы даже знаете, например @pipisabot. Да, я запилил бота для меряния пиписьками с друзьями в чатах 😁 Но на Расте, с открытым кодом, с системным генератором случайности (судя по повторяющимся значениям в рандоме Пиписы, там используется дефолтный генератор Питона или что-то похожее). В отличие от конкурентов, у моего решения есть ряд преимуществ: 1️⃣ Отсутствие рекламы, вообще и навсегда; ну по крайней мере в виде отдельных чисто рекламных постов. Заявляю это как главную фичу и отличие от обнаглевших конкурентов, рассылающих порой по 3+ сообщения в день. 2️⃣ Возможность играть без добавления бота в чат, используя встроенные запросы и кнопку обратного вызова (подсмотрел механику у @fr0staman_bot). 3️⃣ Возможность выбрать Писюн Дня (опять же позаимствовано у @fr0staman_bot). 4️⃣ Возможность подтянуть и импортировать данные из ботов конкурентов путём ответа на их сообщение с топом. Пока работает для двух ботов, пишите свои предложения. 5️⃣ Мультиязычность, правда пока только из русского и английского языков. 6️⃣ Полный вывод рейтинга, а не только первых позиций. В будущем планируется также несколько новых механик: 1️⃣ PvP-битвы (как у @fr0staman_bot); 2️⃣ глобальный рейтинг; 3️⃣ ежемесячные ивенты. Итак, сам бот: @DickGrowerBot Исходный код: https://github.com/kozalosev/DickGrowerBot Для своих дорогих подписчиков также предоставляю бонусные 10 см в виде промокода kozaloru10. Используйте его в личке бота с помощью команды /promo kozaloru10. Но только когда уже создадите пиписьки во всех интересующих вас чатах!
06.11.2023


Давно ничего не писал, провалившись с головой в осенний тильт. Всё-таки дождливый Питер слишком располагает к негативным рефлексиям и противопоказан для обитания без ежедневной чашки горячего какао, пледа и теплоты семейного очага. Ещё на прошлой неделе должен был случиться официальный релиз нового проекта (бота), поскольку я почти дописал документацию, но карты опять не сошлись с созвездиями. Зато в четверг побывал на митапе по Джаве, где один спикер рассказал, почему фреймворк Kafka Streams хоть и может выглядеть соблазнительно простым на первый взгляд и для самых типовых случаев потоковой обработки данных, но превращается в боль и мучительный поиск способов заткнуть дыры костылями при любой попытке шагнуть вправо или влево, а второй пробежался по различным расширениям для JUnit, помогающим либо избавиться от повторения кода, либо сделать тесты более надёжными. Если чуть подробнее про проблемы Kafka Streams, то в основном это невозможность более тонкой конфигурации дефолтного поведения умного фреймворка. Например, там нельзя отключить автокоммит оффсета (однако можно выставить время в Long.MAX_VALUE, что почти то же самое). Дальше у них возникли проблемы при реализации и инвалидации кэшей, а также создании отдельного топика под ошибочные сообщения, где хотели назначать партиции вручную. Без презентации тяжело вспомнить детали точнее, но предпосылками было увеличение производительности, которая с конфигурацией по умолчанию оказалась сильно ниже ожидаемой, и предоставление сопровождению возможности перезапуска сообщений после исправления данных. Ну а последние три дня я перешёл в режим латентной подготовки к поиску работы и прохождению тех. собеседований, так что начал повторять базу и заполнять пробелы в знаниях самоучки, обнаружившиеся при проектировании последних ботов. Так что в ближайшие дни можно ожидать интересные (надеюсь) посты про базы данных. Всем хорошей недели, стабильной психики, добрых мыслей и прекрасной погоды! P.S. Если увидите меня на митапе, то не стесняйтесь подходить)
21.10.2023


» https://www.opennet.ru/opennews/art.shtml?num=59965 » https://habr.com/ru/news/768914/ Блядь... Мне кажется, нас всех крупно поимели. В общем, пока все выпускали через Let's Encrypt сертификаты для SSL, и думали, что он защитит от MitM по пути от сервера к клиенту, никто и не ожидал, что можно MitM устроить по пути от сервера к самому Let's Encrypt. И устроил это не российский интернет-регулятор, как можно было бы ожидать, а, по всей видимости, немецкий. Я пока еще не понимаю все детали атаки, но по моему представлению, хостер (Hetzner) по чьему-то требованию поставил перед сервером другой комп, через который перенаправил порт 80 и сделал запрос на выпуск сертификата с проверкой HTTP-01 (.well-known/acme-challenge). Let's Encrypt посчитал это авторизованными действиями и выдал новый серт, ведь промежуточный комп смог пройти проверку HTTP-01. После этого они смогли перешифровывать другим сертификатом весь трафик на порту 5222. Всё. Никому и в голову не могло придти, что так тоже можно. Для пользователя такая подмена сервера работает прозрачно. Что мне не понятно — почему так плохо всё с Let's Encrypt. Неужели действительно не предусмотрено никакой защиты, кроме как проверки challenge-response. Так можно митмнуть все сервера в мире руками хостеров, и никто ничего не заметит. Никто не застрахован и никаких следов не останется. Только если б можно было как-то запретить HTTP-01 challenge для своего домена и оставить DNS-01 (и надеяться что DNS-хостер не подсунет такую же свинью). Что еще более страшно — если так начнут делать местные хостеры или оборудование ТСПУ. Тогда всё, пиздец. Если даже в «цивилизованном мире» уже практикуют такое, то от своих ждать остаётся недолго. Что еще важно: Hetzner до выяснения всех обстоятельств мы больше не используем, ибо зашквар у них хоститься при таких приколах.
21.10.2023


А вот вам интересное чтиво на тихое субботнее утро 🍿 Кто-нибудь пользовался Hetzner'ом? Если теперь будете искать, куда перекатиться, то есть вариант даже с оплатой серверов в иностранных ЦОДах за рубли. Ну а если не хочется, то можно настроить фикс.
20.10.2023


Нативные языки набирают популярность в бекэнд-разработке. В этой сфере уже сделало себе имя детище Google — Go, а теперь ему дышит в спину Rust, который пока ещё не так известен в этой сфере, но я вижу у него большое будущее. Мощная система типов как у функциональных языков вроде Scala (а ещё развитая система макросов) и одновременно низкое потребление памяти и высокая производительность как у Go. И отсутствие болячек C++ в виде обилия UB, тяжелого наследия 90х и хаоса управления зависимостями. А самое главное - под него уже есть несколько ошеломляющих своей гибкостью и функциональностью Web-фреймворков, самый популярный из которых имеет почти 23 миллиона загрузок на crates.io! Но какой же выбрать? Популярности мало, хотелось бы видеть тесты производительности. А их почему-то очень не любит выдавать Google по запросу "Фреймворк А vs Фреймворк B". Потому что их никто не пишет или потому что их никто не читает? 🤔 Я решил это проверить — так и родилась моя статья https://eternal-search.com/axum-vs-actix-vs-rocket. Кстати, она имеет версию на английском языке, которой вы можете поделиться со своими забугорными коллегами!
20.10.2023


Друже @kiv_apple наконец-то вновь завёл канал (@kiv_apple_blog) и обновил движок веб-бложика, переписав всё на Rust, что мы, разумеется, всецело одобряем 👍 Если Вам интересны французские пейзажи, эмигрантские будни ░░░, бэкенд, программирование, робототехника и прочая айтишечка — обязательно подписывайтесь!
13.10.2023


В прошлый раз не раскрыл тему, как работают хэндлеры с переменным количеством аргументов — исправляюсь. Поскольку в Rust'е нет variadic generics, то dptree просто макросами генерирует 10 вариантов возможной функции, которые принимают от 0 до 10 аргументов. Причём типы должны быть не только Sync + Send + 'static, но ещё и реализовывать трейт Clone, поскольку хоть внутри мапы объект и хранится в Arc'е, в хэндлеры передаётся склонированная версия. Похожий механизм применяется и в DI-контейнере axum. Ну а упомянутый в предыдущем посте крейт refinery уже нет смысла использовать, потому что sqlx теперь сам содержит модуль миграций — sqlx::migrate, которому можно скормить тот же самый пул соединений и не тащить дополнительный драйвер для СУБД
12.10.2023


Всё новое — это хорошо забытое старое
10.10.2023


А спонсор моего возвращения в инфополе — возможность скрыть папку с архивными чатами из списка чатов и убрать их из расчёта непрочитанных сообщений. Идеальный вариант для ОКРщиков, чтобы не выходить из закрытых сообществ, но при этом не сидеть там целыми днями. А также для каналов, на которые подписываешься ради розыгрышей или ботов