Новиков > путь в Big Tech – Telegram
Новиков > путь в Big Tech
184 subscribers
94 photos
192 links
От зеро-кодинга на стройке до написания высоконагруженных сервисов в Big Tech. 

Пишет SWE в Avito.ru (backend), в прошлом: .NET developer и сертифицированный специалист по использованию BIM.

Написать автору: @nvkv_ai

Книги: https://boosty.to/time2code
Download Telegram
День 6

Результат работы:
1. Получение всех автомобилей (REST-ручка).
2. Получение всех водителей (REST-ручка).
3. Получение всех предприятий (REST-ручка).
4. Получение значений таблички со связями между водителями и автомобилями (REST-ручка).
5. Схематическое изображение всех табличек в БД (черновик).

#проект
День 7

Задание
:
1. Добавить модель Manager (менеджер) - наследник от стандартного пользователя, для которого нужна авторизация.
2. Предприятию могут принадлежать несколько менеджеров.
3. Менеджеру могут "принадлежать" (быть видимыми) несколько предприятий.
4. Менеджер получает в REST-запросах только объекты видимых ему предприятий.
5. Сделать случай, когда три предприятия 1,2,3 и два менеджера, одному принадлежат предприятия 1,2, другому 2,3.

Ход работы:
1. Завел модельку Manager (в основном понадобился только файл миграции, но не сама гошная структура).
2. Создал табличку manager_enterprise, чтобы хранить связку менеджер-предприятие, по которой я впоследствии достаю все предприятия, принадлежащие менеджеру.
3. Добавил стандартную мидлвару BasicAuth(), которая идет с джином из коробки и с ее помощью по адресу: /admin авторизую менеджера по связке логин/пароль и затем выдаю ему список его предприятий.

Подумать:
1. Почитать больше про middleware.
2. Изучить JWT-аутентификацию.

#проект
День 8

Задание
:
Изучить, что такое curl, и организовать с его помощью запрос машинок с авторизацией менеджера, как было в браузере в предыдущем задании.

Ход работы:
1. Прочитал по диагонали документацию.
2. Для организации запроса добавил path /admin/vehicles (доступный только через авторизацию), через который выдаю все машинки, принадлежащие менеджеру, через привязанные к нему предприятия. То есть теперь менеджер сможет посмотреть и список всех предприятий (/admin/enterprises), и машин.

Запрос с авторизацией выглядит так:
curl -v --user ismirnov:one http://localhost:8080/admin/vehicles.

#проект
День 9

Задание
:
Добавить поддержку анти-CSRF (если ещё не была включена).

Ход работы:
1. Изучил, что такое CSRF.
2. Добавил поддержку анти-CSRF в проект. При этом какой-то нативной у Gin'а не оказалось, но существуют разные библиотеки, которые работают с переменным успехом. Сейчас в проекте используется одна из таких библиотек, но лишь частично, так как из коробки она не заработала, как ожидалось (при этом документации на нее нет), поэтому я немного ее докрутил, чтобы реализовать анти-CSRF механизм.

В результате запросы, требующие авторизации, обязательно проверяют X-Csrf-Token заголовок. Если он пришел и валидный, то запрос выполняется, если же нет - то отклоняется. В идеальном случае хочу от вышеупомянутой библиотеки отказаться со всем и сделать реализацию со своей логикой: при авторизации генерим секретный ключ, который сохраняем в сессии, а дальше на основании ключа и соли делаем токен, который прикладываем к запросу.

#проект
День 10

Задание
:
1. Сделать REST-добавление новой/изменение полей существующей заданной машинки, и её удаление -- через PUT/POST/DELETE, после того как менеджер авторизовался.
2. Проверить из curl.

Ход работы:
1. Добавил механизм авторизации для добавления/изменения/удаления машинок (по аналогии с прошлым заданием).
2. По curl проверил - без авторизации (включая анти-CSRF) не могу выполнять соответствующие запросы - получаю ошибку 401 (Unauthorized).

#проект
День 11

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

Ход работы:
1. Написал утилиту для генерации: фактически отдельный скрипт в cmd-директории.
2. Для запуска утилиты нужны 3 аргумента: список айди предприятий разделенных ';', кол-во генерируемых машин и водителей.
- Каждая 10 машина получает активного водителя (водитель выбирается произвольно из всего списка, относящегося к предприятию).
- Из интересного: для генерации VIN хожу GET-запросом на randomvin за очередным значением.

#проект
День 12

Задание
:
Сгенерировать для 3 предприятий по 3-5 тысяч машин и водителей (активный водитель для каждой 10-й машины например), и разобраться, как через REST API получать их в режиме пагинации -- не все разом, а листать страничками по 20-50 машинок.

Ход работы:
1. Сгенерировал для предприятий 3-5 тысяч машин и водителей. При этом довольно быстро обнаружил недостаток первой версии генератора, так как отрабатывал он очень долго:
- Переписал его с использованием го-рутин с необходимой синхронизацией между потоками, что сильно его ускорило.
- Раньше для получения VIN'а у меня был GET-запрос в сторонний сервис и это, конечно, сильно просадило перф, так как запросы батчевые туда недоступны, а делать тысячи запросов очень дорого, поэтому пришлось также от этого решения отказаться в пользу примитивной генерации строки (использовал юникс-время).
2. Пагинацию построил на параметрах строки запроса через: limit=50&offset=2500 - получение 50 позиций с отступом 2500.

#проект
Карьера на одном листе

Удобно переносить свои мысли на бумагу / диаграммы или куда-либо еще. Так со стороны можно оценить прошедший путь и запланировать ресурсы на предстоящий.

По ощущениям, я сейчас подхожу к середине своей карьеры, как программист. Вероятно, по этому такое говорящее название "middle".

Крупными мазками наметил планы на ближайшие 3-4 года. Карьерную лестницу спроецировал на грейды Авито (очень нравится их система и по ней действительно просто оценивать свой уровень).

Можно заметить, что 2025-26 года отмечены развилкой. Когда ты достаточно опытный (скажем senior), то у тебя появляется выбор: продолжать развиваться как технический специалист или же пойти по менеджерскому треку.

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

#карьера
👍1
День 13

Задание
:
1. Разобраться с бутстрапом (https://getbootstrap.com/) - как он интегрируется с gin.
2. Сделать простую форму ввода логина-пароля, менеджер заходит через неё и видит список всех своих видимых предприятий.

Ход работы:
Добавил бутстрап-формочку для ввода логина/пароля. После авторизации менеджеру доступны его автомобили.

#проект
Не выработал еще систему регулярного постинга, чтобы не пропускать дни :(

Стараюсь исправляться. После обеда будет еще один "День" разрабатываемого проекта.
День 14

Задание
:
Добавить несложный интерфейс для менеджера -- добавление/редактирование/удаление машинок в выбранном предприятии.

Ход проекта:
1. После того, как менеджер авторизировался, он получает список всех машинок, а также возможность провалиться в панель администратора по синей кнопке.
2. На панели администратора доступны все машины менеджера и он также может, выбирая предприятие, создавать/обновлять/удалять машины.

#проект
День 15

Задание
:
1. Добавить предприятию локальную таймзону (если не задана, тогда считается UTC).
2. Сделать для машинок какое-нибудь поле, связанное с датой-временем (например, дата и время покупки), которое в машине (на сервере) всегда хранится как UTC.
3. Выводить его в запросах API и в UI с учётом таймзоны предприятия, и с учётом, что у клиента в браузере скорее всего своя локальная таймзона (показать надо соответственно в его таймзоне).

Ход проекта:
1. Добавил новое int поле для предприятий - смещение от UTC. Также добавил поле для машин - время и дата покупки (хранится в UTC).
2. В UI клиент увидит время в соответствии с его локацией. API возвращает json, где хранится дата с тайм-зоной (у последнего предприятия тайм-зона не задана).
3. Пришлось в текущий запрос добавить полный JOIN, чтобы из предприятия забирать сдвиг от UTC, который затем добавляю таймзоной к дате автомобиля и уже ее выдаю на клиента. (Полный для того, чтобы также получать записи, где таймзона не задана).

#проект
День 16

Задание
:
Экспериментальное задание - подумать самостоятельно как лучше реализовать:
1. Надо хранить трек -- набор точек GPS, условную поездку автомобиля с привязкой к нему.
2. То есть, как оптимальнее хранить трек, в котором может быть много (потенциально неограниченное) количество gps-точек.

Ход проекта:
1.
Так как непонятно, насколько сложные вычисления с использованием gps-точек нас ждут, то от использования какого-нибудь PostGis для PostgreSQL отказался.
2. Посмотрел Geopoint для Go и мне показался он слишком несерьезным (даже тестов на функции не увидел), чтобы использовать в проекте. Есть как будто более интересная библиотека golang-geo, но так как у нас пока нет расчетов, то использовать тоже не стал.
3. Самым интересным решением мне показалось использовать Redis. При этом я собираюсь хранить активные треки по ключам, а точки для них добавлять через команду Редиса доступную из коробки `GeoAdd`. Завершенные маршруты собираюсь бэкапить в какое-нибудь хранилище.
4. Таким образом, сигнатура основного метода, который добавляет gps-точку к треку следующая:
AddPointToTrack(ctx context.Context, point GPSPoint, track VehicleTrack) error

Где GPSPoint и VehicleTrack имеют следующие структуры:
type VehicleTrack struct {
ID, VehicleID int64
}

type GPSPoint struct {
longitude, latitude float64
}

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

#проект
День 17

Задание
:
1. Добавить в REST API выдачу точек трека по заданному автомобилю и диапазону дат/времени с учётом локальной таймзоны предприятия (сами точки на сервере хранят дату время в UTC).
2. Выдавать их по отдельной настройке либо в json, либо в geoJSON (на выбор пользователя).

Ход проекта:
1. Добавил ендпоинт, который при передаче параметров (vehicleID и дат) будет выдавать точки соответствующие параметрам запроса с поправкой на сдвиг от UTC, который есть у предприятия (если даты не передать, то точки будут выданы все:
- /gps/track?vehicle=1&start=2015-01-01&end=2022-01-01

2. Также добавил возможность получить ответ в geoJSON, если передать соответствующий параметр в строку "geoJSON":
- /gps/track?vehicle=1&start=2015-01-01&end=2022-01-01&geoJSON

#проект