В последние несколько лет крайняя тренировка года в бассейне проходит для нашего любительского спортивного клуба в виде какого-нибудь упахательного заплыва, например, 50 раз по 100 м вольным стилем в режиме 2 минуты на каждый отрезок, или 5 раз по 1000 м кролем в разной экипировке — словом, освобождаем место под оливье как можем 🥣
Но в этот раз, заговорив о планах на конец года, мы вдруг вспомнили, что почему-то давно не играли в водное поло, и сошлись на том, что было бы здорово завершить плавательный год, устроив это дружескоерубилово развлечение 🤽♂️
На удивление, нас собралось полноценные 2 команды: по 6 игроков в поле и 1 вратарь. Таймы решили сделать по 5 минут. В начале это казалось как-то несерьёзно (мало), но уже в конце первого тайма в наших покрасневших от воды глазах отчётливо читалось: "Батюшки, неужели это только начало!?" Да, даже для опытных вотерполистов (а среди нас были и такие) с непривычки этомесилово мероприятие оказалось весьма трудозатратным 🫠
Не знаю, как остальные, а я где-то к середине игры всё же как-то вработался и несмотря на усердноетопилово воздействие со стороны защитников противника таки сумел забить один гол. Правда, ещё две голевых передачи продолбал. Тем не менее, наша команда выиграла со счётом 3:1 🏐
После игры мы всей гурьбой (вместе с болельщиками, коих было чуть ли не столько же, как игроков) плотно заполнили собою небольшую каморку в здании бассейна, полопали мандаринов, поделились впечатлениями и поздравили с Новым Годом тренера, который играл вместе с нами — без него всё это бы не состоялось 🍊
Едва ли такоемочилово занятие можно рекомендовать всем подряд в качестве популярного вида спорта, но если вдруг обычное плавание вам кажется скучным, однообразным и/или недостаточно динамичным, обратите внимание на водное поло. Наверняка вам очень (не) захочется в этом поучаствовать🤪
#спорт
Но в этот раз, заговорив о планах на конец года, мы вдруг вспомнили, что почему-то давно не играли в водное поло, и сошлись на том, что было бы здорово завершить плавательный год, устроив это дружеское
На удивление, нас собралось полноценные 2 команды: по 6 игроков в поле и 1 вратарь. Таймы решили сделать по 5 минут. В начале это казалось как-то несерьёзно (мало), но уже в конце первого тайма в наших покрасневших от воды глазах отчётливо читалось: "Батюшки, неужели это только начало!?" Да, даже для опытных вотерполистов (а среди нас были и такие) с непривычки это
Не знаю, как остальные, а я где-то к середине игры всё же как-то вработался и несмотря на усердное
После игры мы всей гурьбой (вместе с болельщиками, коих было чуть ли не столько же, как игроков) плотно заполнили собою небольшую каморку в здании бассейна, полопали мандаринов, поделились впечатлениями и поздравили с Новым Годом тренера, который играл вместе с нами — без него всё это бы не состоялось 🍊
Едва ли такое
#спорт
🔥18👍1🙈1
Вот теперь с Наступившим! 🎉 🎄 🎁
Последние дни и часы минувшего года у меня прошли отнюдь не налегке — нужно было подготовить и провести две большие презентации по итогам года: 30 декабря для коллег и 31-го для родсвтенников (это такая семейная традиция; я рассказывал о ней год назад). А поскольку хотелось порадовать и тех, и других, пришлось хорошенько потрудиться, поэтому к праздничной полуночи мне хотелось уже не тусить и поздравляться, а упасть лицом в мягкий салат и булькать там до конца каникул 🥘
К счастью, это занятие надоело раньше, и вот я снова на связи. Надеюсь, и вы отметили хорошо! 🙏🏻
Чтобы всё же принести хоть какую-то пользу этой заметкой, поделюсь с вами инструментом, который здорово выручил меня при подготовке семейной презентации. Поскольку почти все мои родственники живут в разных местах, мне давно хотелось как-то визуализировать их места пребывания на карте. Я уже совершал несколько подступов к этому снаряду в прошлые годы (в основном, через сервсиы Google), но успехом они ни разу ни разу не увенчались: получалось то сложно, то стрёмно, то 2-в-1 🪣
На сей раз с помощью DeepSeek я набрёл на бесплатный сервис MapChart, который как раз позволяет рисовать географические карты, кастомизированные под многие специфичные нужды. Основной порядок работы с ним довольно прост:
1. Выбираете базовую карту, например, весь мир, Европу, отдельную страну или несколько.
2. Разукрашиваете мышкой интересные вам регионы: целые страны, штаты/субъекты или их комбинации.
3. Экспортируете в картинку и используете на своё усмотрение 🗺
Конечно, это далеко не всё, что может потребоваться (например, если нужно показать на карте отдельно выбранные города), но для простых сценариев вполне достаточно. Например, мне нужно было отобразить две страны и подсветить в них определенные регионы. Результат в виде готового слайда прилагаю (подписи наносил отдельно, чтобы анимировать их) 👇
Из любопытного: среди базовых сервис предлагает карты фантастических, в том числе игровых миров и возможность строить свои карты альтернативных сценариев истории: https://www.mapchart.net/wargames.html
Только если залипнете, чур не жаловаться, что это я показал🤭
Последние дни и часы минувшего года у меня прошли отнюдь не налегке — нужно было подготовить и провести две большие презентации по итогам года: 30 декабря для коллег и 31-го для родсвтенников (это такая семейная традиция; я рассказывал о ней год назад). А поскольку хотелось порадовать и тех, и других, пришлось хорошенько потрудиться, поэтому к праздничной полуночи мне хотелось уже не тусить и поздравляться, а упасть лицом в мягкий салат и булькать там до конца каникул 🥘
К счастью, это занятие надоело раньше, и вот я снова на связи. Надеюсь, и вы отметили хорошо! 🙏🏻
Чтобы всё же принести хоть какую-то пользу этой заметкой, поделюсь с вами инструментом, который здорово выручил меня при подготовке семейной презентации. Поскольку почти все мои родственники живут в разных местах, мне давно хотелось как-то визуализировать их места пребывания на карте. Я уже совершал несколько подступов к этому снаряду в прошлые годы (в основном, через сервсиы Google), но успехом они ни разу ни разу не увенчались: получалось то сложно, то стрёмно, то 2-в-1 🪣
На сей раз с помощью DeepSeek я набрёл на бесплатный сервис MapChart, который как раз позволяет рисовать географические карты, кастомизированные под многие специфичные нужды. Основной порядок работы с ним довольно прост:
1. Выбираете базовую карту, например, весь мир, Европу, отдельную страну или несколько.
2. Разукрашиваете мышкой интересные вам регионы: целые страны, штаты/субъекты или их комбинации.
3. Экспортируете в картинку и используете на своё усмотрение 🗺
Конечно, это далеко не всё, что может потребоваться (например, если нужно показать на карте отдельно выбранные города), но для простых сценариев вполне достаточно. Например, мне нужно было отобразить две страны и подсветить в них определенные регионы. Результат в виде готового слайда прилагаю (подписи наносил отдельно, чтобы анимировать их) 👇
Из любопытного: среди базовых сервис предлагает карты фантастических, в том числе игровых миров и возможность строить свои карты альтернативных сценариев истории: https://www.mapchart.net/wargames.html
Только если залипнете, чур не жаловаться, что это я показал🤭
🔥6❤3
Завершаю тему итогов года статистикой #спорт 📊
Физкультуры в минувшем году почему-то оказалось больше, чем в предыдущих, хотя планов таких не строил и обещаний никому не давал, даже себе. Вот как это выражается в цифрах (в скобках изменение к 2024 году):👇
● 2154 (+587) км преодолено бегом, на лыжах и вплавь 📏
Строго говоря, это бесполезная цифра, так как складывать километры на лыжах с км вплавь — это как сравнивать теплое с мягким, но подобная цифра есть во многих публичных отчётах, поэтому я включил её и сюда.
● 281 (+53) ч проведено на тренировках ⏱️
Это уже куда более адекватная метрика, отражающая мою "тренировочную способность", но её надо воспринимать с щепоткой соли (см. ниже*).
● 17 (+4) соревнований, в которых принял участие 🏆
Парочка из них были сдвоенными (типа в субботу один старт, в воскресенье другой), но я считаю их по отдельности, потому что у них разные дистанции, протоколы, медали, а у некоторых и дисциплины, например, акватлон+плавание.
* Примечание к длительности тренировок. Простота интерфейса спортивных часов позволяет мне относительно точно фиксировать периоды отдыха на тренировках, благодаря чему теперь можно ответить на вопрос (голосом жены с руками на боках): "А сколько из этого времени ты реально двигался?" Оказывается, коэффициент булкования (©) в этом году составил аж 11,23%, то есть из 281 часов тренировок аж 32 часа я провёл без движения, болтая на бортике в бассейне, фотая красоты на пробежках и заправляясь чаем из поясного бака на лыжах. 1,5 суток в год на такие дела, представляете? Вот так старость и подступается 👨🦳
Из наиболее ярких спортивных достижений года отмечаю:
● лыжный марафон (50 км) в Томске в марте — мой третий марафон наряду с беговым и плавательным 3️⃣
● большой SwimRun (33 км) под Питером в июне — лютая гонка среди чудесных лесов и озёр 🏞
● беговой полумарафон (21,1 км) в Новосибирске в сентябре — ещё раз обновил личный рекорд до 1:25:11 👟
Год выдался славным на физкультурные дела, здесь есть чем гордиться, но я отношусь к этому больше как к приятному стечению обстоятельств, нежели как к личному достижению. И поэтому же не зарекаюсь и даже не обещаю эти результаты превзойти. Куда важнее сохранить постоянство, пусть даже ценой сокращения объёмов и/или результатов. Ну а пока просто продолжаем тренироваться ✊
Прилагаю несколько слайдов по этой теме со своей недавней презентации ☝️
А как прошёл 2025 спортивный год у вас? Давайте делиться результатами 🙂
Физкультуры в минувшем году почему-то оказалось больше, чем в предыдущих, хотя планов таких не строил и обещаний никому не давал, даже себе. Вот как это выражается в цифрах (в скобках изменение к 2024 году):👇
● 2154 (+587) км преодолено бегом, на лыжах и вплавь 📏
Строго говоря, это бесполезная цифра, так как складывать километры на лыжах с км вплавь — это как сравнивать теплое с мягким, но подобная цифра есть во многих публичных отчётах, поэтому я включил её и сюда.
● 281 (+53) ч проведено на тренировках ⏱️
Это уже куда более адекватная метрика, отражающая мою "тренировочную способность", но её надо воспринимать с щепоткой соли (см. ниже*).
● 17 (+4) соревнований, в которых принял участие 🏆
Парочка из них были сдвоенными (типа в субботу один старт, в воскресенье другой), но я считаю их по отдельности, потому что у них разные дистанции, протоколы, медали, а у некоторых и дисциплины, например, акватлон+плавание.
* Примечание к длительности тренировок. Простота интерфейса спортивных часов позволяет мне относительно точно фиксировать периоды отдыха на тренировках, благодаря чему теперь можно ответить на вопрос (голосом жены с руками на боках): "А сколько из этого времени ты реально двигался?" Оказывается, коэффициент булкования (©) в этом году составил аж 11,23%, то есть из 281 часов тренировок аж 32 часа я провёл без движения, болтая на бортике в бассейне, фотая красоты на пробежках и заправляясь чаем из поясного бака на лыжах. 1,5 суток в год на такие дела, представляете? Вот так старость и подступается 👨🦳
Из наиболее ярких спортивных достижений года отмечаю:
● лыжный марафон (50 км) в Томске в марте — мой третий марафон наряду с беговым и плавательным 3️⃣
● большой SwimRun (33 км) под Питером в июне — лютая гонка среди чудесных лесов и озёр 🏞
● беговой полумарафон (21,1 км) в Новосибирске в сентябре — ещё раз обновил личный рекорд до 1:25:11 👟
Год выдался славным на физкультурные дела, здесь есть чем гордиться, но я отношусь к этому больше как к приятному стечению обстоятельств, нежели как к личному достижению. И поэтому же не зарекаюсь и даже не обещаю эти результаты превзойти. Куда важнее сохранить постоянство, пусть даже ценой сокращения объёмов и/или результатов. Ну а пока просто продолжаем тренироваться ✊
Прилагаю несколько слайдов по этой теме со своей недавней презентации ☝️
А как прошёл 2025 спортивный год у вас? Давайте делиться результатами 🙂
🏆8👍3❤1
Про Caddy ⚙️
Помимо безудержного переедания, вопиющего нарушения режима сна и прочих непотребств, эти каникулы я посвящаю одному семейному IT-проекту, до которого раньше никак не доходили руки. Расскажу о нём отдельно в другой раз, а пока — об одной его подзадачке 👇🏼
Возникла потребность принимать на публичном сервере HTTPS-траффик с клиентских устройств, терминировать на нём TLS и отправлять дальше в прикладной сервис. В общем, типичная работёнка для обратного прокси-сервера. Заодно хотелось бы избежать головняка и расходов на SSL-сертификаты (намекаю на Let's Encrypt) и обеспечить перенаправление http(80)->https(443). Значит, нужен какой-то веб-сервер. Благо, варианты есть 📚
1️⃣ Мой собственный опыт в этой сфере сводится только к настройке Apache HTTPD — я вдоволь "наигрался" с этим сначала в универе, потом на работе. Вариант рабочий, но в 2026-ом году, пожалуй, нет, спасибо; здоровье дороже 🤢
2️⃣ В интернетах >80% ответов на подобный запрос сводятся к совету брать Nginx+Certbot — эта связка настолько популярна, что под неё есть даже готовые решения (пример), правда, со своими особенностями применения. В какой-то момент я уже принял мысль, что пойду этим путём, но всё же почти страничный конфиг и 10+ шагов инструкции по его применению не давали покоя, и я решил покопать дальше ⛏️
3️⃣ Модно-молодёжный вариант решения — Traefik — входная точка для микросервисов, поддерживает применение Let's Ecnrypt серфтификатов из коробки и ещё кучу всего. Но вот эта куча меня как раз и смутила — показалось, что это целый комбайн с тонной фич, которые мне не нужны, но за которые придётся "платить" ресурсами машины, а у меня их кот наплакал. Возможно, это заблуждение, но всё же решил поискать ещё 🔍
4️⃣ И тут наткнулся на Caddy — полнофункционональный, но при этом (вроде как) легковесный веб-сервер на Go, главными фичами которого заявлены полная автоматизация настройки TLS и простота конфигурации. Оба пункта прозвучали для меня очень вкусно, и я решил попробовать 😋
После недолгих изысканий я понял, что весь мой конфиг будет состоять из всего 3 строчек в специальном декларативном Caddyfile:
При первом запуске Caddy увидел, что Let's Encrypt сертификата ещё нет, и автоматически провернул всю процедуру по его получению, а она, кто не в курсе, отнюдь не тривиальна:
* нужно инициировать запрос на выпуск
* пройти т.н. challenge (проверку владения доменом, она бывает 3 типов)
* получить и применить сам сертификат (+ключ)
* настроить перенаправление траффика 80->443.
Так вот Caddy всё это сделал сам с первого раза, чем уже меня порадовал 🪄
Но оставалось опасение, что он будет прожорлив по ресурсам. В качестве бенчмарка (и основного применения) я стал заливать через Caddy на сервер бинарные данные по 100 МБит/с каналу на протяжении нескольких часов с регулярным наблюдением за состоянием витуальной машины. Перед этим я проводил аналогичную процедуру через SSH-туннель — хуже точно не стало, а кое в чем (по мелочи) даже лучше. Это, конечно, не полноценный нагрузочный тест, но для моих целей он пройден ✅
Возможно, мне просто повезло с тем, что Caddy пришёлся кстати именно в моём случае, но 69К звёзд на его GitHub позволяют думать, что он всё же реально неплох, поэтому в следующий раз, когда потребуется поднять реверс-прокси, сбалансировать нагрузку или просто удобно раздать статику, я намерен применить его снова. Предлагаю взять его на заметку и вам 📝
#инструменты
Помимо безудержного переедания, вопиющего нарушения режима сна и прочих непотребств, эти каникулы я посвящаю одному семейному IT-проекту, до которого раньше никак не доходили руки. Расскажу о нём отдельно в другой раз, а пока — об одной его подзадачке 👇🏼
Возникла потребность принимать на публичном сервере HTTPS-траффик с клиентских устройств, терминировать на нём TLS и отправлять дальше в прикладной сервис. В общем, типичная работёнка для обратного прокси-сервера. Заодно хотелось бы избежать головняка и расходов на SSL-сертификаты (намекаю на Let's Encrypt) и обеспечить перенаправление http(80)->https(443). Значит, нужен какой-то веб-сервер. Благо, варианты есть 📚
1️⃣ Мой собственный опыт в этой сфере сводится только к настройке Apache HTTPD — я вдоволь "наигрался" с этим сначала в универе, потом на работе. Вариант рабочий, но в 2026-ом году, пожалуй, нет, спасибо; здоровье дороже 🤢
2️⃣ В интернетах >80% ответов на подобный запрос сводятся к совету брать Nginx+Certbot — эта связка настолько популярна, что под неё есть даже готовые решения (пример), правда, со своими особенностями применения. В какой-то момент я уже принял мысль, что пойду этим путём, но всё же почти страничный конфиг и 10+ шагов инструкции по его применению не давали покоя, и я решил покопать дальше ⛏️
3️⃣ Модно-молодёжный вариант решения — Traefik — входная точка для микросервисов, поддерживает применение Let's Ecnrypt серфтификатов из коробки и ещё кучу всего. Но вот эта куча меня как раз и смутила — показалось, что это целый комбайн с тонной фич, которые мне не нужны, но за которые придётся "платить" ресурсами машины, а у меня их кот наплакал. Возможно, это заблуждение, но всё же решил поискать ещё 🔍
4️⃣ И тут наткнулся на Caddy — полнофункционональный, но при этом (вроде как) легковесный веб-сервер на Go, главными фичами которого заявлены полная автоматизация настройки TLS и простота конфигурации. Оба пункта прозвучали для меня очень вкусно, и я решил попробовать 😋
После недолгих изысканий я понял, что весь мой конфиг будет состоять из всего 3 строчек в специальном декларативном Caddyfile:
<мой_домен> {
reverse_proxy http://<адрес_моего_сервиса>
}При первом запуске Caddy увидел, что Let's Encrypt сертификата ещё нет, и автоматически провернул всю процедуру по его получению, а она, кто не в курсе, отнюдь не тривиальна:
* нужно инициировать запрос на выпуск
* пройти т.н. challenge (проверку владения доменом, она бывает 3 типов)
* получить и применить сам сертификат (+ключ)
* настроить перенаправление траффика 80->443.
Так вот Caddy всё это сделал сам с первого раза, чем уже меня порадовал 🪄
Но оставалось опасение, что он будет прожорлив по ресурсам. В качестве бенчмарка (и основного применения) я стал заливать через Caddy на сервер бинарные данные по 100 МБит/с каналу на протяжении нескольких часов с регулярным наблюдением за состоянием витуальной машины. Перед этим я проводил аналогичную процедуру через SSH-туннель — хуже точно не стало, а кое в чем (по мелочи) даже лучше. Это, конечно, не полноценный нагрузочный тест, но для моих целей он пройден ✅
Возможно, мне просто повезло с тем, что Caddy пришёлся кстати именно в моём случае, но 69К звёзд на его GitHub позволяют думать, что он всё же реально неплох, поэтому в следующий раз, когда потребуется поднять реверс-прокси, сбалансировать нагрузку или просто удобно раздать статику, я намерен применить его снова. Предлагаю взять его на заметку и вам 📝
#инструменты
Caddy Web Server
Caddy - The Ultimate Server with Automatic HTTPS
Caddy is a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go
👍17🔥7
Верхняя полка📝
Расскажу о нём отдельно в другой раз
Вероятно, картина покажется вам знакомой, если я скажу, что мой семейный фотоархив представляет собой хаотичное месиво фоток и видео, разбросанных по телефону, облаку (куда они льются сами) и домашним дискам/флешкам. И вряд ли стоит пояснять, что в таком виде эти (в общем-то весьма дорогие мне) воспоминания легко потерять, неудобно пересматривать и весьма трудоёмко искать 🙁
Конечно, я давно осознавал, что надо навести здесь порядок. И ещё долго бы продолжал просто осознавать, если бы накануне Нового Года случайное невысокое падение внешнего HDD с огромной кучей фоток не превратило его в тыкву и не обошлось в несколько десятков килорублей на восстановление. И вот тогда "надо" внезапно превратилось в "пора"... ⏰
Под "навести порядок" я принял для себя следующее:
1. Организовать надёжное хранение в едином месте, но с резервированием локально и в облаке
2. Обеспечить автоматическое добавление снимков и видео с телефонов с попутной фильтрацией дубликатов и каталогизацией
3. Предоставить быстрый поиск по людям, датам, местам и объектам с любого авторизованного устройства (для родственников) 🎯
Раньше почти все эти цели достигались использованием Google Photos, но в новых реалиях от него пришлось отказаться, а достойных альтернатив на российском рынке я не нашёл (хотя и попробовал платный Яндекс.Диск). К тому же захотелось получить больше контроля и возможностей, поэтому я решил попробовать self-hosted решение и выбрал Immich — opensource'ный аналог Google Photos, который мне когда-то порекомендовал Артём @artipop Шабуров. Этот сервис превосходит конкурентов не только по числу звёзд на GitHub, но и по зрелости фич, а это для меня очень важно 🔝
Я развернул его c помощью Docker Compose на российском VPS с 2 ядрами CPU, 4 ГБ памяти и 1,5 ТБ места на HDD. Такой сервер обошёлся в 1400 руб/мес на первые три месяца (новогодняя акция), потом будет порядка 1900 руб/мес (хостинг FirstVDS). В целом, основное взаимодействие с сервисом при такой его скромной мощи пока что полностью устраивает: лента скроллится, видосики грузятся, поиск ищёт и находит. Основной дискомфорт вызывает только извлечение метаданных из загружаемых медиа файлов — для мощного поиска под капотом у Immich работает целая банда моделей машинного обучения, а оно на голом CPU работает, мягко говоря, не быстро — чуть ли не бОльшую часть каникул VPS лопатил круглые сутки на полную мощность, чтобы отсмотреть все мои фото/видео и правильно их проиндексировать (векторизовать картинки, извлечь тексты, распознать людей и т.д.) Мне даже пришлось увеличить ему размер SWAP-файла, чтобы во время распознавания Python-процесс не прибивался OOM Killer'ом. Впрочем, такой объём данных требуется обработать лишь раз; дальше медиа файлы будут добавляться поштучно, и минутная задержка на их индексацию кажется вполне приемлемой 👌
Зато теперь у меня наконец-то появилось более-менее целостное, управляемое и удобное хранилище, в котором на сегодня:
• 42К фотографий (уже без дубликатов и почти без "мусора")
• 3,5К видеозаписей
• 20 лет воспоминаний (плюс несколько сотен оцифрованных бумажных снимков более старшего возраста) 📷
Следующими шагами будет настройка резервирования на домашнее сетевое хранилище (заказано, едет) и постепенное наведение смыслового порядка: разметка людей (имена, даты рождения), уточнение дат съёмки, удаление лишних снимков и т.п. Наверняка на этом пути ещё выяснятся какие-нибудь неприятные моменты, но пока впечатление об Immich как сервисе очень даже позитивное. Особо порадовали:
• удобное мобильное приложение (наряду с сайтом)
• мощное распознавание людей (в том числе в полоборота, в том числе детей, в том числе в очках/масках и в воде)
• клёвый контекстный поиск (запросы типа "закат на пляже", "пятнистый кот на руках у мальчика", "девушка на мотоцикле" исполняются на ура) 🪄
Намерен продолжать осваивать и рассказывать вам по мере появления новых любопытных наблюдений. А если у вас уже есть свой опыт в решении подобных задач, поделитесь — нам наверняка есть, чему поучиться друг у друга 🙂
Конечно, я давно осознавал, что надо навести здесь порядок. И ещё долго бы продолжал просто осознавать, если бы накануне Нового Года случайное невысокое падение внешнего HDD с огромной кучей фоток не превратило его в тыкву и не обошлось в несколько десятков килорублей на восстановление. И вот тогда "надо" внезапно превратилось в "пора"... ⏰
Под "навести порядок" я принял для себя следующее:
1. Организовать надёжное хранение в едином месте, но с резервированием локально и в облаке
2. Обеспечить автоматическое добавление снимков и видео с телефонов с попутной фильтрацией дубликатов и каталогизацией
3. Предоставить быстрый поиск по людям, датам, местам и объектам с любого авторизованного устройства (для родственников) 🎯
Раньше почти все эти цели достигались использованием Google Photos, но в новых реалиях от него пришлось отказаться, а достойных альтернатив на российском рынке я не нашёл (хотя и попробовал платный Яндекс.Диск). К тому же захотелось получить больше контроля и возможностей, поэтому я решил попробовать self-hosted решение и выбрал Immich — opensource'ный аналог Google Photos, который мне когда-то порекомендовал Артём @artipop Шабуров. Этот сервис превосходит конкурентов не только по числу звёзд на GitHub, но и по зрелости фич, а это для меня очень важно 🔝
Я развернул его c помощью Docker Compose на российском VPS с 2 ядрами CPU, 4 ГБ памяти и 1,5 ТБ места на HDD. Такой сервер обошёлся в 1400 руб/мес на первые три месяца (новогодняя акция), потом будет порядка 1900 руб/мес (хостинг FirstVDS). В целом, основное взаимодействие с сервисом при такой его скромной мощи пока что полностью устраивает: лента скроллится, видосики грузятся, поиск ищёт и находит. Основной дискомфорт вызывает только извлечение метаданных из загружаемых медиа файлов — для мощного поиска под капотом у Immich работает целая банда моделей машинного обучения, а оно на голом CPU работает, мягко говоря, не быстро — чуть ли не бОльшую часть каникул VPS лопатил круглые сутки на полную мощность, чтобы отсмотреть все мои фото/видео и правильно их проиндексировать (векторизовать картинки, извлечь тексты, распознать людей и т.д.) Мне даже пришлось увеличить ему размер SWAP-файла, чтобы во время распознавания Python-процесс не прибивался OOM Killer'ом. Впрочем, такой объём данных требуется обработать лишь раз; дальше медиа файлы будут добавляться поштучно, и минутная задержка на их индексацию кажется вполне приемлемой 👌
Зато теперь у меня наконец-то появилось более-менее целостное, управляемое и удобное хранилище, в котором на сегодня:
• 42К фотографий (уже без дубликатов и почти без "мусора")
• 3,5К видеозаписей
• 20 лет воспоминаний (плюс несколько сотен оцифрованных бумажных снимков более старшего возраста) 📷
Следующими шагами будет настройка резервирования на домашнее сетевое хранилище (заказано, едет) и постепенное наведение смыслового порядка: разметка людей (имена, даты рождения), уточнение дат съёмки, удаление лишних снимков и т.п. Наверняка на этом пути ещё выяснятся какие-нибудь неприятные моменты, но пока впечатление об Immich как сервисе очень даже позитивное. Особо порадовали:
• удобное мобильное приложение (наряду с сайтом)
• мощное распознавание людей (в том числе в полоборота, в том числе детей, в том числе в очках/масках и в воде)
• клёвый контекстный поиск (запросы типа "закат на пляже", "пятнистый кот на руках у мальчика", "девушка на мотоцикле" исполняются на ура) 🪄
Намерен продолжать осваивать и рассказывать вам по мере появления новых любопытных наблюдений. А если у вас уже есть свой опыт в решении подобных задач, поделитесь — нам наверняка есть, чему поучиться друг у друга 🙂
Immich
Self-hosted photo and video management solution. Easily back up, organize, and manage your photos on your own server. Immich helps you browse, search and organize your photos and videos with ease, without sacrificing your privacy.
👍13🔥3🤔1
Guice — dependency injection для искушенных 💉
В нынешней enterprise-разработке, где слово "Java" стало чуть ли не синонимом слову "Spring", многие даже не задумываются, что волшебная аннотация
В одной из недавних задач мне нужно было выделить из нашей платформы специфичный для одного заказчика функционал в отдельный плагин. Но если с выбором фреймворка для самого плагина всё было понятно (у нас используется PF4J и вполне устраивает), то для управления зависимостями внутри плагина нужно было что-то подыскать, так как решение из платформы в плагине работало плохо 👎
Конечно, можно было взять модуль
Кроме того, поскольку плагин будет поддерживаться партнёром, для которого Java — отнюдь не основной стек, очень желательно, чтобы в решении было как можно меньше "магии", а если что-то пойдёт не так, то ошибки были максимально понятными 💎
Вот поэтому я вспомнил про Guice — фреймворк внедрения зависимостей, разработанный в Google почти одновременно со Spring (в 2006) и до сих пор используемый у них в production. В отличие от всемогущего Spring'а, целеустремлённый Guice решает только одну задачу, но делает это с очень сильным акцентом на ясность и предсказуемость 🎯
Это проявляется, в основном, в том, что в Guice нет никакого classpath scanning, т.е. конфигурации зависимостей должны быть прописаны явно. Для удобства предусмотрено исключение в виде т.н. Just-In-Time Bindings (привязок, создаваемых на лету), но их логика максимально проста, а для особо строгих случаев их можно вообще отключить. В остальном фреймворк, по сути, просто заставляет разработчика отделятьмух от котлет конфигурацию зависимостей от их применения 🪚
Еще из интересных отличий Guice от Spring:
— объекты по умолчанию в IoC контейнере не создаются синглтонами, а инстанциируются на каждое обращение;
— описывать конфигурацию зависимостей можно не только аннотациями, но и на специальном DSL;
— ошибки разрешения зависимостей представляют из себя целые отчёты, зачастую с советами по исправлению 🔖
Отдельными плюсами для меня стали простая возможность внедрять зависимости в уже существующие объекты (создаваемые PF4J), а также возможность заинжектить инжектор (🤪) — это позволяет в особо упоротых местах перейти от dependency injection к service locator. Такое можно вытворять и в Spring, но по-хорошему лучше избегать с любым фреймворком 🫠
Мой прошлый опыт работы с Guice, где его внедрили до меня, трудно считать на 100% успешным, но ещё тогда мне показалось, что если этот фреймворк применять как задумано его создателями и в более полном объёме, то он может раскрыться во всей красе и позволить работать с ним "благодаря", а не "вопреки". Кажется, моя недавняя задача подтвердила эту гипотезу ✅
К слову, у Google есть и другой DI-фреймворк — Dagger, обретший популярность в Android разработке. Его основная фишка в том, что он работает в compile-time. Такой подход открывает массу полезных возможностей и ограничений, но это уже совсем другая история... 📖
В нынешней enterprise-разработке, где слово "Java" стало чуть ли не синонимом слову "Spring", многие даже не задумываются, что волшебная аннотация
@Autowired в Spring'е, которая обеспечивает автомагическое появление одних бинов в других, — это лишь одна из имплементаций паттерна Dependency Injection (внедрение зависимостей), и уж тем более не допускают мысли, что есть и другие имплементации. Ибо зачем?.. 🤔В одной из недавних задач мне нужно было выделить из нашей платформы специфичный для одного заказчика функционал в отдельный плагин. Но если с выбором фреймворка для самого плагина всё было понятно (у нас используется PF4J и вполне устраивает), то для управления зависимостями внутри плагина нужно было что-то подыскать, так как решение из платформы в плагине работало плохо 👎
Конечно, можно было взять модуль
spring-core, ведь в него входит Spring IoC Container, который как раз этим всем и занимается. Но это показалось мне избыточным, так как кроме DI туда входит и немало других, совершенно не нужных мне фич:It adds:
• Easier integration with Spring’s AOP features
• Message resource handling (for use in internationalization)
• Event publication
• Application-layer specific contexts such as the WebApplicationContext for use in web applications.
Кроме того, поскольку плагин будет поддерживаться партнёром, для которого Java — отнюдь не основной стек, очень желательно, чтобы в решении было как можно меньше "магии", а если что-то пойдёт не так, то ошибки были максимально понятными 💎
Вот поэтому я вспомнил про Guice — фреймворк внедрения зависимостей, разработанный в Google почти одновременно со Spring (в 2006) и до сих пор используемый у них в production. В отличие от всемогущего Spring'а, целеустремлённый Guice решает только одну задачу, но делает это с очень сильным акцентом на ясность и предсказуемость 🎯
Это проявляется, в основном, в том, что в Guice нет никакого classpath scanning, т.е. конфигурации зависимостей должны быть прописаны явно. Для удобства предусмотрено исключение в виде т.н. Just-In-Time Bindings (привязок, создаваемых на лету), но их логика максимально проста, а для особо строгих случаев их можно вообще отключить. В остальном фреймворк, по сути, просто заставляет разработчика отделять
Еще из интересных отличий Guice от Spring:
— объекты по умолчанию в IoC контейнере не создаются синглтонами, а инстанциируются на каждое обращение;
— описывать конфигурацию зависимостей можно не только аннотациями, но и на специальном DSL;
— ошибки разрешения зависимостей представляют из себя целые отчёты, зачастую с советами по исправлению 🔖
Отдельными плюсами для меня стали простая возможность внедрять зависимости в уже существующие объекты (создаваемые PF4J), а также возможность заинжектить инжектор (🤪) — это позволяет в особо упоротых местах перейти от dependency injection к service locator. Такое можно вытворять и в Spring, но по-хорошему лучше избегать с любым фреймворком 🫠
Мой прошлый опыт работы с Guice, где его внедрили до меня, трудно считать на 100% успешным, но ещё тогда мне показалось, что если этот фреймворк применять как задумано его создателями и в более полном объёме, то он может раскрыться во всей красе и позволить работать с ним "благодаря", а не "вопреки". Кажется, моя недавняя задача подтвердила эту гипотезу ✅
К слову, у Google есть и другой DI-фреймворк — Dagger, обретший популярность в Android разработке. Его основная фишка в том, что он работает в compile-time. Такой подход открывает массу полезных возможностей и ограничений, но это уже совсем другая история... 📖
GitHub
GitHub - google/guice: Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 11 and above, brought…
Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 11 and above, brought to you by Google. - google/guice
👍9🔥5👨💻3❤2🤔1
После очередной рабочей встречи нужно было быстренько накидать календарный план работ по фронту и бэкенду к предстоящему демо фичи. По смыслу отлично подходит диаграмма Гантта. Но как бы её попроще нарисовать?.. 🤔
Раньше я их в чём только не делал: от примитивной раскраски ячеек в Excel до монструозного MS Visio. Но в последние годы нравится вести почти все рабочие заметки в Markdown, и на сей раз покидать уютный редактор Typora тоже не хотелось. К счастью, в нём нашлось подходящее решение 👇🏼
Typora поддерживает Mermaid — библиотечку на JS для рендеринга различных диаграмм по простому текстовому описанию (как PlantUML, но без сервера). Идея внедрения этой штуки в Markdown-документ сводится к тому, что вы добавляете блок кода с указанием языка
Именно диаграммы Гантта я рисовал с помощью Mermaid впервые.
Что понравилось (основное):
✅ понятный синтаксис — можно разобраться, просто взглянув на готовый пример
✅ гибкость задания сроков — можно произвольно связывать начала и концы этапов между собой, и при сдвиге одного остальные пересчитаются сами
✅ учёт выходных — их можно автоматически разметить серым фоном и исключить из расчётов
Чего не хватило (основное):
❌ управления масштабом — при авторасчёте он нередко "схлопывает" границы дней, делая диаграмму менее наглядной
❌ гибкости описания секций — чтобы можно было написать секцию и исполнителя разными стилями для читабельности
❌ простановки отдельных дат — в документации для этого описан тег
Конечно, возможности Mermaid сильно не дотягивают до полноценных графических редакторов. Но всегда ли это нужно? Зачастую гораздо проще и быстрее накидать что-то несложное прямо в коде/документе, и вот здесь такие #инструменты, как Mermaid, подходят как нельзя кстати 👍🏼
Раньше я их в чём только не делал: от примитивной раскраски ячеек в Excel до монструозного MS Visio. Но в последние годы нравится вести почти все рабочие заметки в Markdown, и на сей раз покидать уютный редактор Typora тоже не хотелось. К счастью, в нём нашлось подходящее решение 👇🏼
Typora поддерживает Mermaid — библиотечку на JS для рендеринга различных диаграмм по простому текстовому описанию (как PlantUML, но без сервера). Идея внедрения этой штуки в Markdown-документ сводится к тому, что вы добавляете блок кода с указанием языка
mermaid, пишите в нём "код" диаграммы, а редактор сам на лету отрисовывает её сразу же под блоком кода. При этом в финальном документе кода видно не будет — он как бы спрятан за диаграммой. Выглядит код примерно так:gantt
dateFormat YYYY-MM-DD
axisFormat %d.%m %a
excludes weekends
noscript Примерный календарный план работ до демо
section Бэкенд
П.13 :done, 2026-01-27, 1d
П.6 (лист) :active, list-back, 2026-01-28, 2d
П.9 (граф) : des3, after list-back, 2d
П.19 (мониторинг): des4, after des3, 3d
П.20 (управление): control, after des4, 2d
Именно диаграммы Гантта я рисовал с помощью Mermaid впервые.
Что понравилось (основное):
Чего не хватило (основное):
vert, но похоже, он ещё не везде поддерживается.Конечно, возможности Mermaid сильно не дотягивают до полноценных графических редакторов. Но всегда ли это нужно? Зачастую гораздо проще и быстрее накидать что-то несложное прямо в коде/документе, и вот здесь такие #инструменты, как Mermaid, подходят как нельзя кстати 👍🏼
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
This media is not supported in your browser
VIEW IN TELEGRAM
Dive — способ занырнуть внутрь Docker-образа 🤿
Мне не часто приходится создавать Docker-образы с нуля, но всякий раз после этого возникают одни и те же вопросы:
— А точно ли туда попало всё, что нужно?
— А не попало ли туда что-то лишнее?
— Как вообще выглядит структура папок и файлов внутри образа? 🤔
Особенно много таких вопросов возникает при использовании всяких "нетрадиционных" инструментов, которые обходятся без явного
Обычно ответы на эти вопросы получают путём запуска контейнера из образа и входа в него с каким-нибудь
Подобные задачи отлично решает консольная утилита Dive. Она умеет доставать образы из Docker-демона, анализировать их и показывать:
● из каких слоёв состоит образ (даже если он создан не по Dockerfile'у)
● сколько весит каждый слой
● какие файлы и директории создаёт/меняет/удаляет каждый слой на финальной файловой системе контейнера 🔬
Дополнительно Dive умеет подсчитывать условную "эффективность образа" — это доля размера образа, которая не была потрачена на дублирование или перемещение файлов между слоями. Ни разу не видел, чтобы эта цифра была сколь-нибудь значимой, но звучит прикольно🙂
Лично для меня отдельной большой ценностью утилиты стала возможность просмотра прав на чтение/запись/исполнение каждого файла в образе — это сильно помогает, когда пытаешься понять, из-за чего в контейнере что-то ломается с ошибкой "Permission Denied" 🔐
Если вы еще не пользовались этой штукой, ответственно рекомендую попробовать. К тому же сделать это предельно просто: Dive — это всего-навсего один исполняемый файл, который не требует инсталляции и в 95% случаев обходится без настроек. Вот бы все наши вспомогательные #инструменты были такими же, да?..🤩
Мне не часто приходится создавать Docker-образы с нуля, но всякий раз после этого возникают одни и те же вопросы:
— А точно ли туда попало всё, что нужно?
— А не попало ли туда что-то лишнее?
— Как вообще выглядит структура папок и файлов внутри образа? 🤔
Особенно много таких вопросов возникает при использовании всяких "нетрадиционных" инструментов, которые обходятся без явного
Dockerfile-а, например, Google Jib или Buildpack. Я рассказывал о них в докладе на конференции Joker в 2020 году: https://toparvion.pro/event/2020/joker/ 🍿Обычно ответы на эти вопросы получают путём запуска контейнера из образа и входа в него с каким-нибудь
bash-ем, чтобы походить по файловой системе и посмотреть, что там лежит. Но что если контейнер не запускается или его пока нельзя запускать? И как понять, откуда именно в контейнере взялась та или иная часть директорий или файлов? 🧐Подобные задачи отлично решает консольная утилита Dive. Она умеет доставать образы из Docker-демона, анализировать их и показывать:
● из каких слоёв состоит образ (даже если он создан не по Dockerfile'у)
● сколько весит каждый слой
● какие файлы и директории создаёт/меняет/удаляет каждый слой на финальной файловой системе контейнера 🔬
Дополнительно Dive умеет подсчитывать условную "эффективность образа" — это доля размера образа, которая не была потрачена на дублирование или перемещение файлов между слоями. Ни разу не видел, чтобы эта цифра была сколь-нибудь значимой, но звучит прикольно🙂
Лично для меня отдельной большой ценностью утилиты стала возможность просмотра прав на чтение/запись/исполнение каждого файла в образе — это сильно помогает, когда пытаешься понять, из-за чего в контейнере что-то ломается с ошибкой "Permission Denied" 🔐
Если вы еще не пользовались этой штукой, ответственно рекомендую попробовать. К тому же сделать это предельно просто: Dive — это всего-навсего один исполняемый файл, который не требует инсталляции и в 95% случаев обходится без настроек. Вот бы все наши вспомогательные #инструменты были такими же, да?..🤩
👍9❤4🔥2
Forwarded from SnowOne-канал
До конференции меньше месяца!
Всем привет! Меньше месяца осталось до SnowOne 2026. Программа практически готова, большая ее часть опубликована на сайте.
С момента последнего анонса у нас произошли обновления и усиления по самым разнообразным тематикам докладов:
1) Хардкор: Илья Гаврилин расскажет о том, как в прошлом пытались сделать специальный процессор для исполнения Java, и к чему это привело 🤯
2) Котлин: Александр Соколинский и Эмиль Газизов докопаются до самых тонких деталей реализации корутин (coroutineContext, ContinuationInterceptor, Cancellation и другие)👩💻
3) Хардкор/тестирование: Даниил Степанов покажет, как автоматически генерировать тесты через JDI и при чем тут LLM🐞
4) AI: тут у нас целый трек докладов, про них отдельно расскажем чуть позже. Пока скажем, что Егор Ершов объяснит, как же именно устроены внутри генеративные LLM, а Линар Абзалтдинов представит доклад о Spring AI 🤖
—
Очень скоро программа окончательно финализируется и появится на сайте в виде расписания. А пока напомним, что билеты все еще в продаже!
Увидимся меньше чем через месяц на SnowOne ❄️
Всем привет! Меньше месяца осталось до SnowOne 2026. Программа практически готова, большая ее часть опубликована на сайте.
С момента последнего анонса у нас произошли обновления и усиления по самым разнообразным тематикам докладов:
1) Хардкор: Илья Гаврилин расскажет о том, как в прошлом пытались сделать специальный процессор для исполнения Java, и к чему это привело 🤯
2) Котлин: Александр Соколинский и Эмиль Газизов докопаются до самых тонких деталей реализации корутин (coroutineContext, ContinuationInterceptor, Cancellation и другие)
3) Хардкор/тестирование: Даниил Степанов покажет, как автоматически генерировать тесты через JDI и при чем тут LLM
4) AI: тут у нас целый трек докладов, про них отдельно расскажем чуть позже. Пока скажем, что Егор Ершов объяснит, как же именно устроены внутри генеративные LLM, а Линар Абзалтдинов представит доклад о Spring AI 🤖
—
Очень скоро программа окончательно финализируется и появится на сайте в виде расписания. А пока напомним, что билеты все еще в продаже!
Увидимся меньше чем через месяц на SnowOne ❄️
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
За текущим временным затишьем в канале стоит большой фронт работ по разным направлениям. Со временем, надеюсь, смогу о них рассказать. А пока делюсь лишь первым из результатов 👇🏼
Для тех, кто давно интересовался, будут ли у меня проводиться #тренинги онлайн, и можно ли будет участвовать в них не от компании (лично), есть хорошая новость — скоро всё это будет ✅
И ещё одна новость: поскольку подготовка таких занятий требует довольно больших временных и ресурсных затрат, я решил объединить усилия с другим, ещё более опытным экспертом по производительности JVM — Алексеем Рагозиным, о котором упоминал в прошлых постах. Мы будем проводить тренинги в паре, но в разных ролях: ведущий и соведущий, т.е. один основной, второй на подхвате. Распределение будет меняться от занятия к занятию ⚖️
Посмотреть, какие есть тренинги, их даты, описания и ведущих можно на сделанной нами странице:
https://java-perf-training.github.io/
(если что, фронтенд — не наша сила, сорян)
Регистрация и предварительная запись ведутся через сервис Timepad, где организатором числится Алексей, но я там тоже упоминаюсь 🫡
На сегодня 4 учебных модуля (от одного до трёх занятий в каждом) уже имеют назначенные даты, и на них можно бронировать места. Ещё два пока не имеют дат, но можно записаться в лист ожидания 📋
И последнее: в благодарность за ваш интерес и терпение делюсь с вами промокодом
Надеюсь увидеться со многими из вас на наших тренингах. Буду рад ответить на вопросы и замечания, чтобы помочь решиться 👐
И ещё одна новость: поскольку подготовка таких занятий требует довольно больших временных и ресурсных затрат, я решил объединить усилия с другим, ещё более опытным экспертом по производительности JVM — Алексеем Рагозиным, о котором упоминал в прошлых постах. Мы будем проводить тренинги в паре, но в разных ролях: ведущий и соведущий, т.е. один основной, второй на подхвате. Распределение будет меняться от занятия к занятию ⚖️
Посмотреть, какие есть тренинги, их даты, описания и ведущих можно на сделанной нами странице:
https://java-perf-training.github.io/
(если что, фронтенд — не наша сила, сорян)
Регистрация и предварительная запись ведутся через сервис Timepad, где организатором числится Алексей, но я там тоже упоминаюсь 🫡
На сегодня 4 учебных модуля (от одного до трёх занятий в каждом) уже имеют назначенные даты, и на них можно бронировать места. Ещё два пока не имеют дат, но можно записаться в лист ожидания 📋
И последнее: в благодарность за ваш интерес и терпение делюсь с вами промокодом
POLKA77, дающим скидку 25% на все занятия при регистрации до 22 февраля включительно 🎁Надеюсь увидеться со многими из вас на наших тренингах. Буду рад ответить на вопросы и замечания, чтобы помочь решиться 👐
Тренинги по производительности JVM
Тренинги | Тренинги по производительности JVM
Тренинги по оптимизации производительности Java приложений от экспертов с многолетним опытом.
🔥3😁1