Типа про IT и вот это вот всё — full stack development и современные инструменты, подборки и рекомендации, интересные находки и практические советы. Профессиональный авторский контент.
/health и для статики, абсолютно всё решается POST-запросами, в тело которых можно аккуратно уложить любую параметризацию, а не вот это вот. Действие (action, verb) спокойно выносится в URL, пусть он сам за себя говорит. В моём случае достаточно соблюдать наименование вида /[версия]/[сущность]/[действие]/[признак], например:
/v1/damage/get/shallow — получить все т.н. “верхние маркеры”, опционально принимает набор фильтров и объект пагинации
/v1/damage/create — очевидно
/v1/airalarm/get/all — все объекты другой сущности
/v1/auth — просто действие
И так далее. POST only. Works like a charm. А вы что думаете об этом? In REST we trust или rest in peace?minio:
image: minio/minio
container_name: minio
environment:
- MINIO_ROOT_USER=admin
- MINIO_ROOT_PASSWORD=password
ports:
- 9001:9001
- 9000:9000
command: ["server", "/data", "--console-address", ":9001"]
volumes:
- minio_data:/data
mc:
depends_on:
- minio
image: minio/mc
container_name: mc
volumes:
- type: bind
source: ./minio/entrypoint.sh
target: /usr/bin/entrypoint.sh
read_only: true
environment:
- AWS_ACCESS_KEY_ID=admin
- AWS_SECRET_ACCESS_KEY=password
- AWS_REGION=us-east-1
entrypoint: ["sh", "-c", "/usr/bin/entrypoint.sh"]
volumes:
minio_data:
В entrypoint.sh своя пара строк:
#!/bin/sh until (/usr/bin/mc config host add minio http://minio:9000 admin password) do echo '...waiting...' && sleep 1; done; /usr/bin/mc rm -r --force minio/warehouse; /usr/bin/mc mb minio/warehouse; /usr/bin/mc policy set public minio/warehouse; exit 0;MinIO Client, если что, это вспомогательный инструмент для более лаконичных операций с хранилищами и объектами, never mind. Теперь у вас по
localhost:9001 откроется симпатичный dashboard с вашим личным S3. Что с этим всем делать — вам решать :) 1. docker-compose up хуё-моё
2. poetry run wait-for-it \
--parallel \
--timeout 240 \
--service postgres:5432 \
--service exasol:8563 \
-- echo "postgres and exasol are up and running"
3. poetry run pytest -s systests
Скрипт, разумеется, блокирующий, в этом весь смысл.htop!
Но есть нюанс — Linux only, поэтому всем нам, плотно сидящим на OS X ничего не светит. Это печально.// Было
import { render } from ‘react-dom’;
import App from './App'
const container = document.getElementById('root')
ReactDOM.render(
<React.StrictMode><App /></React.StrictMode>,
contaner,
)
// Стало
import { createRoot } from 'react-dom/client';
import App from './App'
const container = document.getElementById('root')
const root = createRoot(container!)
root.render(<React.StrictMode><App /></React.StrictMode)
Во время рефакторинга я обновил “в том числе и это”, а потом целый час дебажил почему все actions во всём проекте стали вызываться по два раза.
А потому что upgrade notes надо читать внимательнее:
In React 18, StrictMode gets an additional behavior to ensure it’s compatible with reusable state. When Strict Mode is enabled, React intentionally double-invokes effects (mount -> unmount -> mount) for newly mounted components. А в компонентах что? useEffect, а в useEffect дёргается dispatch и API.
Такое поведение наблюдается только в development mode и только с использованием StrictMode. Они называют это фичей, которая помогает отлавливать баги и форсит использование pure functions. Я же в гробу видал такое поведение, поэтому убираем StrictMode из корня и живём нормальной жизнью root.render(<App />)
Заебали всё ломать.shp-файлы в geojson-файлы с помощью инструмента ogr2ogr
2. Сконвертировать geojson-файлы в формат mbtiles через tippecanoe
3. Отрендерить основные osm.pbf данные в mbtiles с помощью tilemaker
4. Смёржить два mbtiles через tippecanoe
Возможен вариант подключения shp-файлов непосредственно в tilemaker, но для этого придётся изучить и модифицировать его конфиг на Lua, который занимается процессингом точек и полигонов. Из коробки, разумеется, ничего не работает, часть данных не отображается, требуется поправка на уровни масштабирования и прочее.
Вся процедура занимает минут 20 и частично автоматизирована. На выходе ожидаем примерно гигабайтный файл ukraine.mbtiles, который теперь нужно как-то отобразить в браузере.
Для этого готовим тайловый сервер, он будет резать всё на тайлы в реальном времени и порционно выдавать клиенту для рендеринга. После недолгих экспериментов я остановился на mbtileserver, потому что zero configuration и простое горизонтальное масштабирование.
Ну а чтобы отобразить тайлы в браузере с привычным look-and-feel, используем MapLibre, форк уже коммерческой Mapbox GL. Для работы ему нужна тема, которая описывает движку как именно отображать эти самые тайлы (шрифты, толщина линий, цвета и многое другое). В своём проекте я использую симпатичную, на мой вкус, OSM Bright.
Интересный факт, конфигурация темы не включает в себя нумерацию зданий, которую, как мне кажется, все хотят по-умолчанию. Также интересный факт, что иногда не понятно где зарыта собака — в процессинге или в рендеринге? Поэтому для анализа mbtiles приходится расчехлять полновесную QGIS.
Ну и на react-map-gl мы заканчиваем нашу цепочку преобразований сырых OSM-данных в красивые перелёты по карте в браузере.mbtiles не стоила 1800 долларов в год. Покажется дикостью, но это всё равно дешевле, чем MapTiler Cloud, MapBox Tile API или Google Maps. Точнее, существует фиксированная цена вместо динамического подсчёта per 1000 tiles. Просто открыть карту это уже около 10 тайлов, если что.
Как и с любым open-source, короче. Хочешь трахаться? На здоровье. Не хочешь? Вот тебе коммерческая поддержка и решения вокруг открытых данных и продуктов. Но если хоть немного разобраться, а полная карта мира не нужна, можно настроить собственный pipeline и сэкономить кучу денег. Ну а для полной карты можно арендовать хороший CPU-инстанс и посчитать всё там, дня за 2-3 он должен справиться.
Карты — это долго, дорого и довольно сложно. В целом, не удивительно, что платные решения платные. Но не настолько же.helm install bla/blabla и у тебя через пару минут на кластере завёлся blabla, automagically. На деле же, у меня не возникло проблем только с bitnami/postgresql и спасибо им за это.
Вот например. В качестве геокодинг-движка активно используется Nominatim, о котором я упоминал в прошлом посте. Сам по себе продукт тоже вызывает у меня вопросы, но ничего более зрелого я не нашёл, поэтому маємо шо маємо. У Nominatim довольно лаконичный API, из которого я использую только /reverse и /lookup. Их полнотекстовый /search абсолютно непригоден для адресного автокомплита (они где-то писали, что так и надо), поэтому для полей ввода адреса, которые вы видите на сайте, у меня собственный набор materialized views с индексами под капотом с дальнейшим реверсом через Nominatim.
Для обработки данных с Прихистка мне потребовалось использовать в том числе и /search, потому что люди на Прихистке вбивают свою локацию в произвольной форме, точно известен только регион, а мне нужен как бы longitude и latitude, чтобы отобразить маркер. И когда настало время выкатываться, стало понятно, что с Nominatim в кластере что-то не так. Приложение, которое делает reverse geocoding через /search падает. Кубер его пытается переподнять, оно снова падает, ну вы поняли.
Смотрю логи контейнера, а там от Nominatim прилетает какой-то непонятный html, потому и падает (оно и должно падать в таком случае). Но почему? Локально работает, остальные endpoint’ы работают, pod явно видит Nominatim… короче странно это всё.
Запрос к API на /search , как я понял, зачем-то редиректился на UI, отчего два вопроса — почему у них такой конфиг Apache и зачем мне на сервере какой-то UI? Оказалось, что в Helm chart’е UI включен по-дефолту. Выключаем. Падает весь Nominatim. Включаем обратно 🙂 Форкаю chart, разбираюсь. Вырезаю весь намёк на UI, чищу немного остальные ямлы, раскатываю уже свою версию. Работает, но не /search. При чём не работает он как-то по-тихому. Смотрю логи Nominatim, а ему нужен какой-то tokenizer.php, но по нужному пути его нет. Гугление ничем не помогло… но почему всё работает локально?
Потому что локально в одном контейнере поднимаются и Postgres, и сервис, а в Dockerfile есть такой интересный трюк, который нельзя применить в случае, когда у тебя база и приложение разнесены. Да, chart сломан. Простое решение — берём локально tokenizer и доставляем его через ConfigMap по адресу. Ура, всё работает! Вот и ночь прошла.
Короче говоря, K8s — это весело.['1', '2', '3', 'a', 'b', 'c', 'd', 'e']
И дано некое число K. Нужно реализовать функцию rotate_left, которая смещает элементы списка на K элементов влево:
['a', 'b', 'c', 'd', 'e', '1', '2', '3']
Можем заодно и rotate_right запилить, чтобы двигать таким же образом вправо:
['c', 'd', 'e', '1', '2', '3', 'a', 'b']
И если вам кажется, что всё очень просто, алгоритм должен отработать за O(n) по времени и O(1) по памяти.
#алкоритмы