Мой web-dev
55 subscribers
62 photos
1 video
66 links
Привет, я php-бэкендер, делюсь своими мыслями и наработками
Download Telegram
Обожаю подобную мазафаку
Помню как выпал, когда первый раз увидел, что в С можно в структурах хранить указатели на функции и пользоваться ими как методами

https://youtu.be/6Riy9hVIFDE?si=XwRbWXaKxIvAc_jF
Ребята, я стал лидом

В среду мне позвонил СТО, сказал, что я закончил испытательный срок
После этого вывалил мне супер инфу о том, что меня назначают лидом, дают команду и большой проект, а сегодня рассказал об этом всем на дейлике
Что думать - я пока хз; пока что просто непонятно как это все будет происходить, опыта-то нет

Вообще, я рад, но я очень надеюсь, что не уйду совсем в менеджерство, слишком люблю кодить
🔥15🫡2
Из-за леса, из-за гор

... прилетела задача по перевозу 13 приложений на выделенную бд.

Когда мы на подработке только начинали пилить все эти приложения, я и подумать не мог, что их столько будет
Поэтому, для каждого приложения в докер композе была завернута база
Ну а что? Это как минимум удобно. И нет, вопросы производительности нас бы не коснулись - масштаб не тот

Но приложений меньше не становится, а смотреть на вывод docker ps становится страшно
Да и бэкапы бы не помешало делать, желательно не через костыли
А хуже всего то, что я не могу через IDE залезть в базу приложения на дев/прод контурах и посмотреть что творится - приходится лезть через ssh на сервак и там уже в контейнере шариться в БД

Поэтому было принято простое решение - сделать выделенный сервак с БД и загнать туда все БД всех приложений
Сказано - сделано. Осталось только в конфигах поменять домен для подключения и можно спокойно жить дальше

Но проблема в том, что мне на месте не сидится и вместе с переездом БД я решил полностью перелопатить раскатывание приложений на проде, деве и локалке
Вышло-то на самом деле очень даже ничего:
1. удобно - вся раскатка делается одной командой
2. нет мусора - теперь есть всего один корневой docker-compose.yml, а вот доп настройки к нему цепляются через docker-compose.override.yml, которые соответствуют нужному окружению
3. универсально - проекты теперь раскатываются и выглядят в плане деплоя как один
4. на всех приложениях теперь php8.2 + jit + opcache
5. редис был успешно везде заменен на файловый кеш (если вообще использовался; было такое, что редис поднят, а коннекта к нему нет)

Без провалов не обошлось - один раз накатил тестовую базу на прод. Но это мелочи :)

В общем и целом опыт очень крутой. Всегда приятно заниматься стандартизацией и улучшением DX
🔥5
Подумал, что давно очень ничего не писал сюда
А что писать? Каждый день теперь это пороховая бочка
Каждый день прилетают задачи, что все горит и уже вчера надо было сдать огромный кусок функционала
Как делать задачи? Да кто знает) последний чел, который знал уже месяц как не работает :D

Звучит как пиздец? Возможно
Но я поймал себя на мысли, что мне этого давно не хватало
Это какой-то особенный азарт решать нерешаемые жопы в краткие сроки и выходить победителем

Да, все пока очень спонтанно и все такое, но мы в начале пути к светлому будущему
🔥6🤝1
Черная полоса вроде закончилась, началась прикольная

Меня недавно добавили в чат, где есть люди из разных областей компании
Разрабы, ПМы, а главное - непосредственные пользователи наших внутренних приложений (операторы)
У последних, как не трудно догадаться, - всегда все горит, ужасно тормозит, работать невозможно, клиенты массово жалуются и тд
Иногда это паника, иногда это реальность

Как раз последние пару дней я разгребал именно реальный случай, когда проду становится плохо
Заходишь в логи, а там бескрайнее море записей с уровнем emergency, в каждой из которых написано про таймаут

Какой-то из 4 сервисов наотрез отказывался укладываться в 20 секунд с ответом
Беда в том, что запросы делались асинхронно, через multicurl и при выбросе исключения не было никакой информации о том, кто именно уходит в таймаут
Спустя какое-то время все же нашел виновника и полез смотреть почему не успевает

А не успевал он по простой причине - на один апи запрос делалось 100500 запросов в базу и в среднем запрос работал около 44-48 секунд
И ладно бы это просто было простыней из вызовов к базе, но нет, все куда хуже
Там тянулась сущность из базы, а потом передавалась в экстратор
Экстрактор в нашем случае это такая шляпа, которой ты даешь список атрибутов, а он их каким-то образом тянет из сущности
И большая часть атрибутов - смежные сущности, за которыми доктрина каждый раз ходила в базу

Решение немного экстремальное, но я просто вытягивал все данные по сущности разом
Да, там много джоинов; да, там жирнющий селект
Но быстрее на стороне пхп эту кучу данных растолкать по сущностям, чем каждый раз ходить в базу

Результат в итоге с одной стороны неплохой - прирост х8 (с 48 секунд до 6 секунд)
С другой - это все равно 6 секунд :(
Но лучшее враг хорошего, поэтому такой результат нас устроит пока что
👍31
господи дай мне сил
с отпуском меня!
до свидания программирование и привет дача!

p.s. а еще нас уже 50😊
🎉10
Локальное окружение в кубере с k3s

Когда я пришел в ферале на текущую работу, то все окружение разворачивалось в minikube.

Я уж не знаю какие именно проблемы с ним были (я их не заметил), но мой, на тот момент, тимлид принял решение переезжать на k3s, подсмотрев удачный опыт у одного из разрабов в компании.

Мне тогда было поручено локально поставить k3s и попробовать развернуть в нем пару сервисов, попутно обновив в них readme.

Собственно, с задачей я справился. Вот только выбранное решение было очень кривым, да еще и ломало dns при включенном корпоративном впне из-за того, что приходилось ставить dnsmasq. Зачем? На тот момент я думал, что общаться между сервисами очень надо через домены вида service-name.dev.loc (просто потому что по-другому я не знал как, а все примеры обращений из гугла не работали). И dnsmasq позволял это делать и оно даже работало в подах кубера. Но, как у любой задачи типа “было бы прикольно”, приоритет выполнения был минимальный и потому она быстро затерялась в недрах личного бэклога.

Прошло полгода, у меня честно говоря от кривости работы локального окружения уже порядком горела жопа. Более того, ко мне приходили разрабы и спрашивали - как вы локально разворачиваетесь? У вас то куча репозиториев с docker-compose’ами, то какой-то кубер, то еще что. И вот случился отпуск, а значит шанс снести к чертям собачим всю систему и начать с нуля.

В этот раз я решил вообще не использовать ничего, кроме самого k3s. И это помогло. Из коробки по прошлой инструкции у меня вообще не работал dns - из пода даже в гугл сходить нельзя было. Я начал копать и понял, что не использовал важную (в моем случае) опцию при установке k3s. А именно - --flannel-backend=wireguard-native . После указания опции все заработало. В гугл теперь можно было ходить, а самое главное - теперь поды могли общаться друг с другом просто через свои имена. Например, my-service-name.application.

Мне и в голову не приходило, что в кубере может быть удобный способ для общения между подами, как в docker compose, например (там можно обращаться к контейнеру по его имени внутри одной сети). Нет, я конечно видел и читал про CoreDNS, даже в конфиги какие-то лазил. Но почему-то в голове выключатель не щелкал.

После всего этого пришлось еще ставить сайдкар на базе нгинкса, чтобы поды могли обрабатывать запросы напрямую от других подов. Но там уже честно говоря не так интересно. Там просто мрак в виде go’шных шаблонов для helm.

Итого, я вроде как меньше стал бояться кубера. Теперь этот зверь кажется более-менее дружелюбным и начинает закрепляться реальное понимание того как там все работает.
Пересел на manjaro

Выше уже писал, что в отпуске решил переставить систему
Отчасти потому, что уже скопилась куча мусора (например, тот же забагованный k3s с dnsmasq)
Отчасти потому, что мне приелся gnome. Да, он красивый и модный - ну и что? Я от его функционала и возможностей использую минимум. Мне надо-то всего 2 рабочих пространства, одно из которых поделено на 4 части (телеграм, терминал и 2 окна браузера). Он был очень хорош как переходное звено с mac os на линукс, но не более. Да и его ужасный встроенный инструмент для тайлинга меня иногда доводил до слез.

Почему именно manjaro - не могу сказать. Смотрел в сторону linux mint и zorin os, но они debian-based, а на дебиане я уже сидел. Не то что бы я прям сильно понимаю в чем отличие arch от debian (кроме rolling release), видимо просто захотелось чего-то новенького.

А вот с графическим интерфейсом все было чуть сложнее.
По началу были мысли вообще накатить i3wm. Сделал загрузочную флешку, посидел один вечер, потыкался. В целом я понимаю почему люди этим пользуются, но у меня ума не хватило вот так нахрапом им овладеть. Я слишком привык к мышке, чтобы раз и навсегда перейти только на клавиатурный способ взаимодействия с системой. По сути это vim в мире графических оболочек. А у меня с vim туго, пусть он и является для меня теперь дефолтным редактором конфигов, где нет возможности использовать phpstorm/vscode.

Посидел, подумал еще - kde я уже пробовал, мне не зашло, от gnome пытаюсь уйти, i3wm сложно. Поэтому начал смотреть в сторону xfce. Опыт с ним у меня уже был, когда я накатывал zorin os себе на ноут. У меня были только максимально положительные впечатления от этого опыта.
Меня смущала пара моментов с привычными мне горячими клавишами, но как оказалось - все системные горячие клавиши можно снести, что я и сделал. Добавил пару новых, накатил темную тему и все! Я как будто дома оказался.
Сказать, что комп летает и все плавно - ничего не сказать. И дефолтный функционал тайлинга работает как часы.
Да, нет красивых менюшек и круглых краев у всех окон - ну и ладно. Меня и так уже потихоньку начинает настигать дизайнерский аскетизм.

Так что я прямо очень советую поставить manjaro + xfce, если хочется чего-то свежего и простого

i use arch btw
Это что было?

Я на прошлой неделе прошел самое невероятное странное собеседование

Во-первых, созвона с эйчар не было.
Меня просто спросили, есть ли вопросы по вакансии.
Ладно, отправил им список. На следующий деньполучил ответ.
В целом, это ок, может просто экономят время.
Но обычно на первичном созвоне эйчар сам должен понять, что рассказать сотрудникам о собеседуемом

Во-вторых, технический собес состоял из часового созвона с эйчар и ответа на огромную кучу технических вопросов. То есть никакого живого взаимодействия с техническими людьми не было.
Но это меня тоже не смутило. Скрининг это не редкое явление. Прошел, эйчар помахал ручкой и сказал, что спишемся.
Ждем следующего этапа

Следующий этап пришел нежданно - в личку на хх сегодня присылают оффер!
То есть оффер просто за скрининг
В какой отдел, с кем работать, какие там люди, что делать - не сказали, мол NDA
Такого я еще конечно не встречал
🤣4
Сколько по-вашему нужно сделать запросов в базу для получения данных для списка (некоторые поля основной сущности + данные из смежных сущностей, где-то с агрегациями) с учетом фильтров?
10? 20? 50? Как насчет 600?)
Именно так и "работало" апи одного из сервисов на подработке
Сначала тянулись все отфильтрованные сущности, потом по каждой сущности отдельно собирался набор данных из кучи методов, в каждом по 1-2 запроса в базу
Работало это все ваще прекрасно: выгрузка из 50 сущностей занимала 7 секунд и делала те самые 600 запросов
Индексов на таблицах было ровно 0)

В целом, наверное, можно было бы забить на это. Да, грязно, криво и работает медленно, но ведь работает же. Большинству людей, которые этим фильтром пользуются, вообще до лампочки - 7 секунд оно выполняется или 0.5, это все-таки не диспетчерская МЧС.
Но есть и меньшинство, которому очень надо делать выгрузку этих отфильтрованных списков в эксель. А это уже совсем другая песня. Вот тут нас и поджидала жопа
Оказывается, иногда выгрузить нужно вообще все строки таблицы (+- 3к). Зачем и почему - опустим, нам не за это деньги платят
Факт в том, что выгрузка в эксель полностью основывается на фильтре. Это удобно и позволяет избежать ненужного дублирования кода
Теперь вспоминаем, что 50 сущностей выгружается за 7 секунд, значит 3000 выгрузится за сколько? Неправильно, не за 420, потому что время выполнения выгрузки растет совсем не линейно

Варианты решения были космические! Давайте прикрутим центрифугу и кролика, чтобы в фоне задачи выполнять и отправлять результат на клиент! Давайте сделаем отдельную страницу с выгрузками, чтобы за ними можно было следить в реалтайме!
Угадайте какой из вариантов был мой :D
Задача из-за обсуждений лежала спокойно в беклоге, а однажды я просто сидел пил кофе и на меня снизошло откровение - а с какого хрена вообще выгрузка такого малого количества записей занимает так много времени?

Из этого получился максимально простой выход - выполнять как можно больше работы за 1 запрос, тем самым максимально снижая время общения с базой. Сам по себе в приложении код очень простой, там экономить нечего
Но тут я немного схитрил: если сейчас запросов 600, то сильно будет разница, если их станет 1 или 2? Я по итогу разделил процесс выгрузки на 2 этапа: поиск идентификаторов сущностей с учетом фильтров и собственно сам сбор данных, используя найденные идентификаторы. Примерно как ведется работа с эластиком

Сам запрос на сбор данных это простецкий селект с под-селектами, в том числе с агрегацией в json-объекты
Если вы из тех людей, которые до сих пор считают, что под-селекты и джсон в постгре это медленно и тупо, то ... может быть вы и правы, но в данном случае это не имеет значения, тут все-таки не хайлоад

По итогу получаем очень даже хороший прирост. Выгрузка 50 сущностей стала занимать 0.9-1с, а экспорт в эксель 700 записей около 2 секунд
Да, не горы свернули, но базе и пользователям жизнь облегчили)
🔥3👍1
Начинаем нашу суперигру "найди ошибку"!

Ошибка в том, что константа CASE_LOWER (равняется 0) используется для функции array_change_key_case, а не для mb_convert_case
Для mb_convert_case в свою очередь есть константа MB_CASE_LOWER (равняется 1)
Таким образом, получаем, что по коду читается, что строка приводится к нижнему регистру, а на самом деле к верхнему (0 интепретируется как MB_CASE_UPPER) 😂
Как добавить динамически формиремую надпись на первой странице пдф файла с помощью пхп?

1. берем пхп, берем mpdf, импортируем пдф файл, формируем нужный хтмл, вставляем, рендерим - готово!
2. молодец, но: пользователь загрузил модный пдф файл версии 1.7, mpdf поддерживает версии до 1.4
3. ставим в контейнер ghostscript, через shell_exec перегоняем пдф в версию 1.4, дальше как прежде - готово!
4. молодец, но: пользователь загрузил пдф с каким-то странным изображением, которое пропадает при прогоне через mpdf
5. убираем импорт через mpdf, с помощью него просто в отдельный файл формируем пдф с отрендеренным хтмл, ставим в контейнер pdftk, а стоп он не поддерживается в alpine ставим в контейнер qpdf, через shell_exec накладываем файл с надписью на загруженный пдф (qpdf --overlay)
6. молодец, но: пользователь загрузил пдф в котором сканы доков, поэтому формат пдф - А0 и вставленная надпись оказывается милипизерной, еще и не в том месте
7. забираем мета-данные загруженного пдф-файла через qpdf --json, находим размеры первой страницы, формируем надпись на формате А4 указывая в хтмл размеры в миллиметрах, через ghostscript меняем размер файла с сохранением всех пропорций до размера загруженного пдф, производим наложение - готово!
8. молодец, но: а нет, пока все нормально, можешь выдохнуть

АААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
🤣2😢1
извините, не могу не поделиться)
😁6
вот вроде бы в наше время все должно быть максимально просто
ты подключил себе интернет на 500 мбит, купил роутер, который такие скорости поддерживает
воткнул кабель в первый попавшийся порт (роутер же гигабитный, какая разница?) и пошел работу работать
а потом сидишь и думаешь - а кого хера такой интернет медленный? speedtest показывает жалкие 30 мбит/с
начинаешь разбираться, грешишь на ОС и железо, правишь конфиги и вроде становится лучше (аж 40 мбит), но все равно херня
а потом лезешь в настройки роутера, долго там лазаешь, проверяя все что можно и натыкаешься на веселое меню, которое тебе говорит, что порт, в который ты воткнул lan-кабель держитв всего лишь 100мбит
идешь перетыкаешь в соседний и вуаля! все начинает просто летать!
и даже в кс1.6 наконец-то пинг не 90, чудеса какие-то!

до заявленных 500 конечно не дотягивает, но в целом я доволен
🔥1
ну что, новая неделя - новая работа?

2 недели назад написал заявление, сегодня вышел на новую
сфера интересная - электронно-торговая площадка; в 23м году уже работал на подобном проекте, было интересно; тут тоже скучно не будет - команда молодая, веселая, проект огромный (9 гигов репа весит)

по увольнению говорить особо не хочется - уходить было жалко, с командой сработались, задачи выполнялись влегкую, но я человек живой, к тому же с семьей, которую надо кормить, и с кредитами, которые надо платить
терпеть не могу, когда эйчары зажимают зарплаты текущим сотрудникам, а у самих на хх висят вакансии с вилкой от твоей зп
и был даже контроффер, но каждые полгода-год вот так вот воевать и с пеной у рта выбивать себе повышение я не готов - это нездоровая херня

постов по техничке пока вообще не ожидается, все было какое-то рутинное последнее время, а ближайшие пару месяцев будет просто онбординг
единственное что я щас пересел на винду 11; в целом ощущение, что поставил какой-то очень модный дистрибутив линукс; wsl2 радует очень сильно однако
ну и в гта4 можно поиграть без помощи рантайма стима)
👍5🔥3😁1
К новому году готов!
🔥6🎄1
Мало кто знает, но оказывается, Ubuntu написана на php!
😭1
Фронт на дейлике выдал:
«Там можно поправить руками, но через жопу, поэтому сегодня весь день ковыряемся в жопе»
🤝3
так, эпопея бугурта про вставку подписи в pdf уже была
в этот раз у нас в меню "шаблонизация docx html'ом"
для справки: используется пакет PhpOffice\PhpWord

прикол в том, что с самого начала начинаются странности - чтобы импортнуть надо создать объект таблицы со строкой и ячейкой и вот уже только ячейку можно наталкивать хтмлом (скрин 1)
на этом вроде бы можно успокоиться, потому что оно в целом работает
но тебе пишут и говорят, что при добавлении отступов они в доке теряются, просто пропадают

я опущу все 5 часов моих страданий, но финальный алгоритм сводится к следующему (скрин 2):
1. оборачиваем пришедший хтмл в <body>
2. импортим через таблицу
3. обернутый хтмл толкаем в DOMDocument и вырезаем все элементы, которые из себя представляют просто символ новой строки
3. проходимся по каждому импортируемому элементу, сопоставляем с нодами в DOMDocument (это на самом деле просто, потому что порядковые индексы элементов совпадают)
4. ищем в нодах стиль вида /padding-(\w+): (\d+)px/
5. выставляем отступ элементу ворда, но не прямым импортом, неееееет; в ворде один таб это 708 попугаев; конвертируйте из пикселей сами)
6. на всякий случай, если не указан отступ, то выставляем насильно 0
7. импортим в шаблон документа

и все это только потому, что ворд не поддерживает хтмл-стиль padding)

скрины в комментах