dev notes – Telegram
dev notes
1.42K subscribers
24 photos
3 videos
170 links
Пишу про Go, Vim, и про то, как я медленно ползу в сторону FAANG.
Веду @digest_golang

С предложениями: @junsenpub
Download Telegram
Некоторое время назад я написал большой гайд о том, как настроить neovim с нуля и привести его к виду, пригодному для разработки: с подсветкой синтаксиса, пониманием кода, автокомплитом, и десятком других возможностей, к которым мы привыкли в IDE.

Мотивация у меня простая. Когда я только начинал разбираться в теме, я не видел ни одного гайда, следуя которому я не столкнулся бы с ошибками или в котором все сразу бы заработало. Большинство авторов или упускают множество моментов, или не раскрывают весь контекст, из-за чего новичку тяжело понять, в чем проблема и как ее решить.

Чтобы это исправить, в своей статье я настраивал neovim на чистой тачке, начиная с установки и конфигурирования консоли и заканчивая тем, что редактор стал похож на IDE.

Затем я перевел статью на английский и опубликовал ссылку на нее на различные тематические ресурсы.
И как показывает статистика, в 2024-ом году писать код в консоли все еще кому-то интересно 🙂

Поэтому я дописал вторую часть, где показал как настроить вторую пачку плагинов, которые вместе с первой составляют мой базовый набор: с ним можно без проблем писать код, иметь интеграцию с гитом и большинство привычных возможностей из IDE.

Го читать - https://poltora.dev/neovim-for-developers-2-ru/
3🔥6👍44
Паттерн Circuit Breaker

Сейчас я работаю над приложением с API с нагрузкой в несколько тысяч RPS. Каждый вызов API, помимо прочего, провоцирует запросы во внешние сервисы. Недавно у меня появилась типичная проблема: если внешний сервис перестает отвечать из-за каких-либо ошибок на его стороне, я хочу, чтобы все новые запросы временно прекращали попытки обращаться к нему. Спустя некоторое время, когда внешний сервис вновь заработает, мы снова начнем делать запросы.

Проблема распространенная, я много раз решал ее сам и видел множество сторонних решений. Объединяет их общий принцип: существует глобальный стейт, доступный всем потокам, в который сохраняется статус внешнего сервиса — работает он или лежит. Каждый обработчик, перед вызовом этого сервиса, читает этот статус и принимает решение: делать вызов или нет.
При этом был какой-то обработчик, который опрашивал внешний сервис, и, если тот начинал отвечать, менял глобальный стейт.

Недавно узнал, что у этого паттерна есть название — Circuit Breaker. Общий принцип паттерна я описал выше, за исключением того, что вместо дополнительного обработчика каноничный подход подразумевает, что через определенный промежуток времени “пропускается” несколько запросов, и, если они успешны, глобальный стейт изменяется.

Нашел хорошую статью с примитивной реализацией с нуля и объяснением, что и как работает: https://rednafi.com/go/circuit_breaker/
Хороший пример, который при желании можно доработать и использовать в своих проектах.
2🔥6👍421
Посмотрел доклад "Debugging Go Application" от Matt Boyle из Cloudflare

Сначала коротко. Итак, у нас что-то сломалось, что делаем:
* Сначала проанализируй код глазами и удостоверься, что ты не видишь явных ошибок;
* Затем пишем тест на участок кода, который потенциально выдает ошибки и проходимся по нему отладчиком;
* Затем покрываем код логами, если он еще не покрыт;
* Затем добавляем метрики: успешные/не успешные запросы, время запроса, etc
* И последний шаг - покрываем код трейсами, если они еще не были добавлены.

Теперь более подробный конспект деталей, которые мне показались интересными.
Про логирование. В прошлом году в Go завезли расширенный логгер - slog, и если ты все еще по какой-то причине используешь стороннее решение, например logrus, то можно смело переезжать.

В коде, который Мэт демонстрирует, используется паттерн передачи логгера через контекст:

ctx := context.Background()
// Create a logger that writes to the log file
logger := slog.New(slog.NewJSONHandler(logFile, nil))
ctx = slogctx.With(ctx, logger)


Тут же объясняется, почему он его использует: Мэт заметил, что в нескольких opensource-решениях гугла используют такой подход, и раз компания, разработавшая этот язык так делает, разработчики Cloudflare посчитали эту практику хорошей, и со временем стали использовать ее в своих проектах.

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

Дальше, переходя к секции с трейсингом, Мэт рассказывает про пакет для сбора метрик от VictoriaMetrics - https://github.com/VictoriaMetrics/VictoriaMetrics. В целом выглядит типично для пакетов подобного рода, но в использовании пакет выглядит проще, чем похожий пакет для Datadog, который я использую в своих рабочих проектах.

Если ты ранее никогда не использовал метрики, то Мэт рекомендует для начала мониторить RED-набор метрик:
- Rate
- Error
- Duration

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

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

https://www.youtube.com/watch?v=7YfFBTkGIOI
1👍8🔥31
Посмотрел еще один доклад, который долго лежал у меня в закладках, на этот раз про отладку параллельного кода в Go - https://www.youtube.com/watch?v=D_S9qQ7jzkQ

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

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

Пакет https://github.com/xiegeo/coloredgoroutine подсвечивает вывод каждой горутины отдельным цветом, что может быть полезно при отладке.

Использование флага GODEBUG=schedtrace позволит вывести отладочную информацию про то, как планировщик управляет горутинами:

➜ GODEBUG=schedtrace=5000 ./main
SCHED 0ms: gomaxprocs=10 idleprocs=8 threads=3 spinningthreads=1 needspinning=0 idlethreads=0 runqueue=1 [0 0 0 0 0 0 0 0 0 0]


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

func main() {
go func() {
// some work...
}()

go func() {
// some work...
}()

go func() {
// some work...
}()


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


func main() {
go func() {
labels := pprof.Labels("fetcher", "main_goroutine")
pprof.Do(ctx, labels, func(ctx context.Context) {
// some work
})
}()

go func() {
labels := pprof.Labels("worker_1", "main_goroutine")
pprof.Do(ctx, labels, func(ctx context.Context) {
// some work
})
}()

go func() {
labels := pprof.Labels("worker_2", "main_goroutine")
pprof.Do(ctx, labels, func(ctx context.Context) {
// some work
})
}()

// ...
}


И затем, в отладчике можно вывести горутину по конкретному тегу:

(dlv) goroutines -l -with label fetcher
Goroutine 21 - User: ./main.go:20 main.main.func1.1 (0x1003befcc) [chan send]
Labels: "fetcher":"main_goroutine"
[1 goroutines]


Хорошая статья, где описывается как это сделать более подробно и где автор показывает ряд других решений для добавления меток в горутины: https://blog.jetbrains.com/go/2020/03/03/how-to-find-goroutines-during-debugging/#using-a-custom-library-to-enable-debugging-labeling

Вторая часть доклада - про deadlock'и и про то, как с ними бороться.
Из полезного, либа, которая помогает найти дедлоки - https://github.com/sasha-s/go-deadlock
К примеру, автор этой библиотеки с помощью нее же нашел потенциальные дедлоки в коде cockroach db: https://github.com/cockroachdb/cockroach/issues/7972
1🔥53👍3
Все начали писать про итоги и планы, и я тоже решил написать.

Изначально этот канал назывался "1000 дней программирования", и я вел его с целью показать мой путь от джуна до синьора, отсюда и id канала - @junsenior. 1000 дней прошли пару лет назад и лычка синьора у меня уже тоже давно есть. В целом, за 5 лет с момента первого поста я успел поменять PHP на Go, поработать в российском бигтехе, а потом перейти на валютную удаленку в большую и быстро развивающуюся компанию, в которой работаю уже полтора года.
В 2024-ом году я не сменил язык и работу (что для меня удивительно), но решил много интересных и сложных задач. Например, за год я развернул несколько сервисов с нуля, много работал с параллельным программированием, много строил архитектуру, рефачил большие объемы кода и собеседовал людей.

Но главный результат этого года для меня - у меня появилось понимание того, к чему я хочу стремиться дальше. А дальше я хочу попасть в бигтех, но уже американский. В идеале - MAANG, под которым я понимаю пару десятков самых больших американских тех-компаний. Дедлайн, который я сам себе выставил, - 3 года (если в ближайшие пару лет нас не заменят нейросети, конечно). Получается, новый челлендж в 1000 дней 🙂

Горизонт работы, для того, чтобы хотя бы собеседование в такую компанию стало возможным, прочерчивается через 3 основных вещи, на которые я буду делать упор.
1 - английский. Очевидно, собеседование будет на английском, и хотя я активно его учу последние пару лет, в ближайшее время я хочу повысить как эффективность этого обучения, так и интенсивность, о чем тоже планирую тут писать.
2 - алгоритмы. У меня уже было несколько подходов к алгосам, но каждый раз не хватало мотивации и усидчивости, и обычно я забрасывал это дело через месяц-два. Сейчас у меня есть и мотивация, и понимание как правильно решать алгосы так, чтобы запоминать решение, и купленный курс по алгосам от @tenfoundation :), который я планирую пройти в ближайшие полгода.
3 - system design. Тут в планах начать с курса от balun.courses, который я тоже купил и теперь жду старта 11-ого февраля. В общем и целом system design мне всегда очень нравился, так что тут не ожидаю никаких проблем, ожидаю только массив полезной и крутой инфы.

О каждом из этих пунктов я буду тут писать и делиться тем, что мне кажется интересным. Так же в планах возообновить стримы (да, олдфаги помнят, как года 3-4 назад я уже пытался это делать), и вернуться к менторству, в том числе и на бесплатной основе, о чем я тоже планирую тут написать.

В общем, планы намечены, что делать - тоже понятно. Впереди много работы, и, надеюсь, много контента, которым я тут буду делиться.

Желаю нам всем, чтобы 2025-ый год стал лучше, чем год уходящий. Мира вам, и с наступающим!
🔥16👍94🎉1
Попробовал на днях Cursor. Если вдруг кто-то еще не сталкивался, то это среда разработки, построенная на основе Visual Studio Code, куда встроена большая языковая модель, которая умеет держать в контексте открытый проект и дописывать его по запросам.

Ощущения - очень крутые ❤️ Открыл рабочий проект, описал на английском, что я хочу и в каких файлах стоит посмотреть пример, и через 10 минут и еще 3 промпта у Cursor написал столько кода, сколько я писал бы часа 2.
Затем он поправил тесты с учетом функционала, который сам же дописал, и суммарно у меня все все, включая освоение интерфейса, ушло минут 30.
В целом - буду использовать, вероятно даже попробую пробную версию и отпишусь потом, стоит ли она того. Как по мне это сильно круче Copilot от github, которым я пользуюсь уже пару лет.

Что еще на мой взгляд круто - так это возможность обучаться с его помощью. Например, я сейчас фоном учу Rust, и Cursor, помимо того, что умеет писать код, создавая все нужные файлы, умеет еще и описывать что происходит в том или ином файле.
Например, ты можешь попросить его создать новый проект на Rust, взять API какого-нибудь сервиса и интегрироваться с ним. А затем попросить его построчно объяснить, что происходит и какая конструкция за что отвечает.

Cursor обработает до 2000-х тысяч правок в коде бесплатно, затем нужно будет заплатить.

Единственный минус - это ощущение, что вся эта история с нейросетями через 3-5 лет очень сильно поменяет рынок труда 🙂
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥6👾2
Как я писал выше - я хочу подготовиться к собесам в FAANG и компаниям около FAANG.

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

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

И вот спустя две недели какие я сделал выводы:
* Как только какая-либо тема начинает получаться, процесс решения задач по этой теме становится интересным. Начал прям кайфовать от того, когда получается написать какой-нибудь алгоритм быстро и завести его с первого раза.
* 🐍Python - очень хорош для алгосов. Когда у тебя есть возможность вызвать str.isalnum(), а не писать свою проверку, что символ в диапазоне нужных значений, это очень упрощает процесс. Плюс, на собесах за это в 99% не спрашивают.
* Подобные задачки развивают умение искать в коде ошибки. Например, у меня в рабочем проекте, из-за его специфики, есть очень много мест где что-то вычисляется, перебирается или проверяется. И частые ошибки, которые пропускают на ревью, это не ошибки бизнес-логики, а ошибки в рассчетах: взяли срез не по нужным элементам или, наприме, забыли добавить что-то к переменной перед тем, как писать ее в метрику. И последнее время замечаю, что становится проще жонглировать такой логикой в голове.

В целом цель на год - отрешать ~150-200 самых частых задач, которые в теории могут быть на собесе.

В заключении скажу, что алгосы - абсолютно точно не панацея. Их стоит отрешивать или если ты хочешь подготовиться к собесу, или если тебе это нравится. В моем случае оба этих фактора совпали 🙂
Please open Telegram to view this post
VIEW IN TELEGRAM
👍92🔥2
Новость из мира Go: завезли proposal, который предлагает добавить в язык оператор ? для обработки ошибок, что позволит вместо привычной обработки:

r, err := SomeFunction()
if err != nil {
return fmt.Errorf("%v", err)
}


писать такую конструкцию:

r := SomeFunction() ? {
return fmt.Errorf("%v", err)
}

Переменная err внутри фигурных скобок автоматически будет доступна и будет содержать ошибку.

Дискуссия получается жаркой, и кажется, что большинству эта идея не нравится, как и мне. Такой сахар - это переусложнения языка, который уже усложнили за последние пару лет дженериками и итераторами (но стоит сказать, что и в первом и во втором есть смысл).
Но менять базовый синтаксис - плохая идея и прямое нарушения философии языка.
👾7🔥5👍3
Как я уже как-то упоминал, я веду небольшой канал с дайджестом статей, материалов и новостей из мира Go - @digest_golang. И вот в процессе подготовки материалов, наткнулся на интересную заметку, которой хочу поделиться: https://antonz.org/go-map-shrink/

Автор рассказывает о том, как сборщик мусора работает с базовым типом map. Если кратко, то все зависит от того, сколько места занимает тип, который хранится в map.
* Если тип занимает < 128B, и мы храним его без указателя, то Go не освобождает выделенную память даже после того, как мы явно удаляем все элементы в мапе:

type Client struct {
id uint64
body [40]byte
}

...

m := make(map[int]Client)
for i := range 10000 {
m[i] = Client{id: uint64(i)}
}

runtime.GC()
printAlloc("after create")

for i := range 10000 {
delete(m, i)
}

runtime.GC()
printAlloc("after delete")



Вывод:

initial: heap size = 47 KB
after create: heap size = 1073 KB
after delete: heap size = 1073 KB


* в случае, если размер типа, сохраняемого в map больше, чем 128B, Go автоматически сохраняет его через указатели на куче, и после явного удаления память будет освобождена:

type Client struct {
id uint64
body [1024]byte
}

// the same logic


Вывод:

initial: heap size = 42 KB
after create: heap size = 11581 KB
after delete: heap size = 331 KB


В случае, если вес структуры <128B, то можно явно сохранять в мапе все значения через указатели, и тогда место будет освобождаться.
Иначе, в примере выше порядка 1Mb памяти останется не убранной, что в случае сложной многопоточной логики может значительно увеличить количество потребляемых ресурсов и это стоит держать в голове. Плюс, эти знания могут пригодиться на собесе 🙂
2🔥6👍31
Новости из мира Go: состоялся релиз Go 1.24 ❤️

Из интересного:
* Полная поддержка алиасов для дженериков, теперь можно делать такие вещи:

type set[P comparable] = map[P]bool

func NewSet[T comparable]() set[T] {
return make(set[T])
}

func main() {
s := NewSet[string]()
s["hello"] = true
fmt.Println(s["hello"]) // true
}


* map в Go теперь работает на основе Swiss Tables (почитать о том что это можно, например, тут или тут), что дает прирост производительности, в некоторых случаях, до 30-40%;
* Улучшена поддержка WebAssembly: добавилась дирректива go:wasmexport для простого экспорта функций в webassembly и добавилась поддержка сборки программы как WASI reactor/library. Уже прилетела свежая статья от go-тимы, где эти улучшения описаны более подробно - https://go.dev/blog/wasmexport

Анонс релиза: https://go.dev/blog/go1.24
Release notes: https://go.dev/doc/go1.24
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍42🔥2😢1
В поиске интересных статей на канал с дайджестом, нашел на реддите пост, где автор рассказывает как он создал минималистичную реляционную БД на Go. Реализация поддерживает транзакции, индексы на основе B+ Tree и покрывает весь базовый набор операций по выборке данных.

Вот его проект: https://github.com/Sahilb315/AtomixDB

На первый взгляд выглядит очень даже неплохо, можно углубиться и разобраться в том, как работают индексы, как можно реализовать простую acid-модель и как в целом реляционная БД может быть устроена.

Меня еще со времен чтения Клеппмана очень зацепила тема внутреннего устройства СУБД, но никак не доходили руки поресерчить ее более тщательно. Кажется, настало время сделать это 📆
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍42👾2
Недавно выше я писал, что собираюсь подготовиться и попробовать пройти в американский или европейский бигтех.

Итак, что было сделано за первые 3 месяца этого года:
1. Прошел курс по system design от balun-cources.
Курс, в целом, неплохой. Очень много теории и практика под конец. Теория полезная, частично пересекающаяся с "Высоконагруженными приложениями"" Клеппмана, но с объяснением на кейсах из реальной жизни. В целом - курс стоит своих денег, хотя лично у меня изначальные ожидания были несколько выше. В любом случае, база получена, осталось попрактиковаться в изученных паттернах как на собесах, так и в реальной работе.

2. Начал проходить курс по алгосам от Влада Тена. С моим темпом прохождения и количеством свободного времени - думаю эта история затянется надолго, но я и не тороплюсь. Зачем вообще нужен курс по алгосам? Лично мне - для дисциплины. Решать задачки проходя курс мне сильно проще, в ином случае я просто забью на середине. А тут за меня уже кто-то продумал структуру задач, объяснил теорию и оформил все это в удобном виде.

3. Английский. Вот этого было действительно много. Зафиналил спринт на 30 занятий на lingoda, и параллельно 3 раза в неделю занимаюсь с нейтивом. Еще для себя обнаружил, что уровень сильно растет вверх от просмотра контента на английском, поэтому каждый день теперь смотрю какие-нибудь сериалы или видосы. В целом - становится лучше, надеюсь в таком же режиме довести его до конца года до того, чтобы проходить/проводить собесы на английском.

Еще из интересного - сходил тут, недавно, на собес. Я почти 2 года работаю в одной компании, пока не планирую ее менять и все эти два года не выходил на рынок. А тут меня позвали и я подумал - почему бы и да, и решил попробовать. Компания - большая, занимается мобильными играми и занимается этим лучше всех в Европе. Но с собесом у ребят, как по мне, большие проблемы.
Мне дали час времени, за который сначала попросили решить задачу, затем провести код ревью строк на 250, а затем написать кусок кода с довольно сложной конкурентной логикой. Задачи - в целом ок, но вот лимит по времени в час - это, конечно, сильно 🙂 За час я успел сделать все 3 задачи, но все 3 - не полностью, особенно код-ревью.
Для себя тут сделал вывод, что буду чаще ходить на собесы, чтобы понимать как сейчас дела на рынке и что там спрашивают.
1🔥8👍63
Итераторы в Go, про которые я несколько раз уже писал на этом канале, релизнули еще в прошлом году, но я так ни разу их и не применил в работе – просто не было задачи, которая не была бы решена без них.

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

Спойлер - они действительно упростили жизнь и где-то даже позволили оптимизировать потребление ресурсов. Я решил выделить паттерны их использования, которые мне показались удобными, и получилась новая статья - https://poltora.dev/iterators-in-go-ru/

Велкоме.
2👍4🔥21💯1
Если раньше большую часть кода я писал в neovim, то сейчас все чаще и чаще у меня параллельно открыт Cursor. Если я понимаю, что время генерации кода курсором будет быстрее, чем время, потраченное на написание промпта для такой генерации - я рационально иду и генерирую его. Это очень круто работает для тестов и для задач в которым мало контекста и зависимостей.

И я давно думал, что было бы очень круто, если бы была возможность объединить простоту и удобство генерации кода через LLM, доступное в Cursor и все фишки neovim, большинство из которых невозможно настроить в Cursor через сторонние плагины.

И как оказалось, такие проекты есть!
Я попробовал два самых популярных:
- https://github.com/yetone/avante.nvim
- https://github.com/olimorris/codecompanion.nvim

avante - самый популярный и имеет наибольшое количество звезд и контрибьюторов, но лично у меня он очень часто и много стрелял багами. Мягко говоря, ему далеко до генерации кода как в Cursor, хотя проект очень интересный и очень надеюсь, что его продолжат развивать.
А вот codecompanion мне понравился. В интеграции с моделями от anthropic качество кода, которое он генерирует - довольно неплохое, и количество багов в процессе работы сильно меньше, чем у avante.

Планирую в ближайшее время взять какую-нибудь более-менее реальную задачу и какой-нибудь проект с небольшим количеством контекста, и сравнить эти плагины на разных моделях (а заодно и chat-плагин для github copilot - https://github.com/CopilotC-Nvim/CopilotChat.nvim, он менее популярен и тоже имеет не мало багов судя по отзывам, но выглядит многообещающе, поэтому его тоже стоит попробовать).
1👍64🔥1
Допрошел на днях большой и многоэтапный собес в один большой и с недавних пор известный финтех из Мексики. Собес прошел, оффер получил, но с компанией не сматчились 😔

Хочу рассказать про второй этап - system design. У меня это был первый сисдиз, который я проходил после прохождения курса по system design от Балуна (так как это не реклама - курс можете нагуглить сами).
Задачу мне дали такую: есть система комментариев в большой социальной сети, комментарии подгружаются синхронно. Хотим сделать это асинхронно и добавить туда поддержку медиа.

До этого я такой задачи не видел, но решить ее получилось, и как сказал интервьювер - получилось решить хорошо. Очень хорошо помогли паттерны из курса: в решении я сделал микс из паттерна по работе с медиа, вкрутил несколько CDC, применил active/passive модель для системы с сокетами, и в итоге схема (приложил ее к посту) получилась рабочей, за исключением некоторых правок. В целом - мне даже понравилось проходить собес в таком формате, курс себя точно оправдал.
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥7👍43
Решил зачелленджить разработку через LLM и реализовать один пет-проект полностью через cursor, и сделал пару интересных выводов.

- Есть такая область разработки - написание парсеров. Я знаю нескольких людей, которые буквально весь свой доход аккумулируют этим занятием, благо на биржах до сих пор множество заказов на парсер того или иного ресурса. Так вот cursor написал мне парсер за несколько часов и пару итераций, который я сам писал бы несколько дней, а-то и неделю.
Алгоритм оказался максимально простым: я сбросил модели ссылку на ресурс, модель сделала curl, получила исходный код, и описала регулярки под все необходимые мне данные, которые мне оставалось только немного подтюнить.
- Оно как бы и очевидно, но убедился лично - если попросить cursor подумать о чем-то, что не связано с кодовой базой, которая в нем открыта - он сделает это сильно хуже, чем gpt4/5. Например, окончив очередную итерацию и убедившись, что часть фукнционала работает - я решил его задеплоить, и попросил проанализировать, где мне лучше это сделать, учитывая специфику проекта и мои лимиты по стоимости. Cursor выдал какую-то дичь, и спустя несколько промптов и вагон контекста так и не смог найти нужной информации. GPT-5 даже без контекста и понимания кодовой базы ищет и аккумулирует такую информацию сильно лучше. По-итогу я пришел к тому, что треть запросов я ищу/собираю через gpt-5, обычно в нескольких чатах внутри отдельного проекта, а всю работу с кодом делаю через cursor.

В целом, по итогам недели работы с LLM по вечерам, я написал кода столько, сколько сам бы писал в том же режиме недели 2-3. Но, несмотря на сильное ускорение, надо быть в контексте всего проекта и постоянно проверять логику - часто модель делает что-то или не оптимально, или неправильно, и в некоторых местах ее нужно поправлять.

Качайте технину и юзайте модели, чуваки. Думаю, что тем, кто не будет этого делать - в ближайшие пару лет на рынке станет сильно сложнее.
28🔥6😢1
Пилю тут пет-проект, связанный с каналами и телеграмом, и обнаружил самый странный способ монетизации.
Используя telegram bot api есть возможность вставить в сообщение кастомный emoji, что мне и нужно было. Каждый кастомный emoji имеет свой уникальный id, и для того, чтобы вставить его в строку, телеграм рекомендует делать следующее: вставить какой-нибудь плейсхолдер, а затем указать его место и длину, чтобы кастомный emoji его подменил.

Но для того, чтобы emoji успешно вставился - нужно купить уникальное имя для бота, внезапно 🤷‍♂️🤷‍♂️🤷‍♂️
Имя покупается на связанной с ton площадке - fragment, и каждая покупка - это аукцион на неделю, где любой пользователь может перебить твою ставку. И после этого или повышай, или выбирай новое имя 🤡
Купил вот, жду, надеюсь не перебьют.
Please open Telegram to view this post
VIEW IN TELEGRAM
25👾1
В рамках пет-проекта я дошел до стадии, когда нужно где-то захостить MVP.

Последний раз, до перехода в большие компании на постоянный найм, я хостил свои проекты лет 7 назад: и хотя тогда все активно докеризировалось и уже почти везде начинали внедрять кубер, но маленькие проекты в маленьких компаниях все еще часто крутились на связках вида linux+nginx+mysql+php. И хотя я и умел докеризировать приложения - прод обычно разворачивался по старинке - без виртуальных контейнеров. Да и запускать в то время виртуальные контейнеры в проде по некоторым утверждением было антипаттерном из-за сильной потери в производительности, особенно учитывая, что все приложения тогда я писал на PHP, который производительностью и так не блистал.

Сейчас же я пошел ресерчить вместе с chatgpt, как и на чем мне лучше все развернуть так, чтобы это было относительно дешево и быстро в настройке, и gpt предложил мне несколько вариантов:
- так как я частично использую google-стек - заиспользовать инструменты гугла и для деплоя: GCP cloud run services / jobs + google cloud storage или внешнюю БД
- второй вариант - fly.io и другие похожие сервисы
- третий вариант - свой vps + dokku

Посчитав экономику, самый дешевый вариант под мои нагрузки получился третий - свой vps + dokku. С dokku я до этого не работал, и открыл для себя этот дивный новый мир.

dokku - это PaaS, который помогает менеджерить lifecycle приложения. По-факту, это набор bash-скриптов, который очень упрощают и оптимизируют работу с докером: одной командой можно создать выделенное окружение, задать туда энвы, настроить количество инстансов, которые будут запускаться в выделенных контейнерах. Не нужно составлять DNS вручную - они одной командой пробрасываются между контейнерами, автозаполняются и становятся доступными для вызова, что очень удобно при работе, например, с postgres.

Одна из вещей, которые мне нужно было захостить - это обработчик для tg-бота.

Упрощенно, это было запущено следующей цепочкой команд:

dokku apps:create tgbot - создание выделенного окружения для приложения
dokku plugin:install https://github.com/dokku/dokku-postgres.git
git remote add dokku-bot dokku@<VPS_IP>:tgbot
dokku config:set \
key=value \
...
dokku postgres:create mydb - создание БД
dokku postgres:link mydb tgbot - проброс DATABASE_URL из mydb в tgbot
dokku ps:scale tgbot worker=1 - запускаем 1 инстанс
dokku ps:report tgbot - проверяем статус


Дальше передеплой приложения выглядит следующим образом - мы вносим правки в код, коммитим и пушим в dokku-bot (git remote source, добавленный выше), и через git hook'и запускается магия автоматической пересборки наших контейнеров.

В ближайшее время настрою связку dokku с github actions, чтобы докручивать кастомные джобы и, например, иметь возможность гонять тесты перед тем, как пересобирать контейнеры с приложениями.
Но базово, для небольших тестовых проектов - кайф ❤️

dev notes | golang digest
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍71👾11
Forwarded from bruhcollective. (iTaysonLab)
the following content will be interesting for Russian-speaking only:

тут начали закупать в ТГ рекламу некого мессенджера "Telega", общающего золотые горы стабильную работу ТГ на территории РФ

но в чем подвох? а в том, что эта "Telega" (которая https://telega.me) - является проектом VK.
но как об этом узнать? а все просто - берем APK и открываем декомпилятор

идем в ru.dahl.messenger.Extra и видим:
-> PROXY_ADDRESS = "dal.mvk.com", прокси-адрес, запишем
-> MYTRACKER_SDK_KEY = "*", SDK-ключ от трекера MyTracker, который принадлежит Mai VK Group
-> CALLS_BASE_URL = "https://calls.okcdn.ru/" - те самые рабочие звонки, которые на самом деле являются звонками через инфраструктуру Одноклассников (на которых работает еще MAX и VK Звонки, ага)

а теперь берем dal.mvk.com:
-> неймсервера mvk.com идут на малоизвестный домен VKONTAKTE.RU
-> в декомпиляции официального клиента VK для Android можно найти референсы на "https://jira.mvk.com"

(и вся реклама этого клиента в ТГ ведет на трекинг-домен trk.mail.ru)

но кому не пофиг? вдруг ВК просто по приколу решили сделать форк ТГ, прикрывшись прокладкой из Татарстана?

а вот тут уже обнаруживается прикольная вещь: в клиенте есть "черный список" нежелательных ТГ-каналов, ботов и пользователей! при нажатии на которых выводится ТГ-шная "заглушка" с своим текстом:

<string name="ContentIsUnavailable">Материалы недоступны</string>
<string name="ContentUnavailableInfo">Этот %1$s недоступен в связи \n с нарушениями правил платформы</string>


какие правила платформы? Telegram? но таких строчек нет в официальном клиенте Telegram :)

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

///

а кроме этого, в клиенте есть замена иконок на ВКшные. все бы ничего, но весь код замены был взят из такого малоизвестного клиента как Catogram (https://github.com/Catogram/Catogram/blob/a34ddfb42f50b86eb7cd83fb68ea24fa041084a9/TMessagesProj/src/main/java/ua/itaysonlab/catogram/vkui/ReplaceKtx.kt)
BaseIconReplace -> ru.dahl.messenger.icons.BaseIconReplacement
No/VkIconReplace -> ru.dahl.messenger.icons.AltIconReplacement/IconReplacementNone
ReplaceKtx.newSparseInt -> ru.dahl.messenger.icons.BaseIconReplacementKt

причем взяли все подчистую - те же названия переменных, методов, параметров и даже код тот же (даже тот же sparseInt сделали root-level функцией Kotlin)

а забавный факт в том, что основной разработкой Catogram занимался... я

как-то так....
2😢13👍4🎉1👾11