Проєкт реалізує бекенд для прийому та обробки лідів у вигляді двох незалежних FastAPI-мікросервісів в одному репозиторії:
landings— приймає ліди з лендингів через APIcore— обробляє ліди у фоні та віддає аналітику
Сервіси не спілкуються між собою напряму. Передача лідів між ними відбувається тільки через Redis.
- Python 3.11+
- FastAPI
- PostgreSQL
- SQLAlchemy 2 + asyncpg
- Alembic
- Redis
- JWT
- Docker Compose
landingsприймаєPOST /leadlandingsперевіряє Bearer JWTlandingsкладе лід у Redis-чергуworkerуcoreчитає Redis-чергуworkerвиконує дедуплікацію і записує лід у PostgreSQLcoreвіддає аналітику черезGET /leads
landings/— API для прийому лідівcore/— API аналітики та фоновий воркерshared/— спільні конфігурації, моделі, auth, Redis, схемиalembic/— конфігурація та міграції БД
Реалізовано 3 обов'язкові таблиці:
affiliates(id, name)offers(id, name)leads(id, name, phone, country, offer_id, affiliate_id, created_at)
Для запитів використовується Bearer JWT.
JWT створюється на основі payload:
{"id": 1}Де id — це affiliates.id.
На кожному запиті:
- токен декодується
- з токена дістається
id - перевіряється, що такий affiliate існує в таблиці
affiliates - якщо affiliate не існує, запит відхиляється
Для POST /lead додатково перевіряється, що affiliate_id у body збігається з id із токена.
У воркері реалізована дедуплікація: якщо лід з такими самими name + phone + offer_id + affiliate_id уже був оброблений протягом останніх 10 хвилин, він не записується повторно в БД.
Проєкт використовує .env з такими змінними:
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=leads_db
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
REDIS_HOST=redis
REDIS_PORT=6379
JWT_SECRET=super_secret_key
JWT_ALGORITHM=HS256docker compose up -d postgres redisdocker compose run --rm core alembic -c alembic/alembic.ini upgrade headdocker compose run --rm core python seed_data.pyСкрипт додає:
Affiliate(id=1, name="Test Affiliate")Offer(id=1, name="Test Offer")
docker compose run --rm core python -c "from jose import jwt; from shared.config import JWT_SECRET, JWT_ALGORITHM; print(jwt.encode({'id': 1}, JWT_SECRET, algorithm=JWT_ALGORITHM))"docker compose up --buildПісля запуску доступна Swagger-документація:
http://localhost:8001/docs—landingshttp://localhost:8002/docs—core
URL:
http://localhost:8001/lead
Headers:
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
Body:
{
"name": "Олексій",
"phone": "+380982342123",
"country": "UA",
"offer_id": 1,
"affiliate_id": 1
}Успішна відповідь:
{
"status": "ok",
"message": "Lead accepted"
}URL для групування по даті:
http://localhost:8002/leads?date_from=2026-04-25&date_to=2026-04-25&group=date
URL для групування по офферу:
http://localhost:8002/leads?date_from=2026-04-25&date_to=2026-04-25&group=offer
Headers:
Authorization: Bearer <JWT_TOKEN>
У проєкті додано міграцію:
alembic/versions/001_create_tables.py
Під час розробки таблиці спочатку створювалися вручну для швидкого старту, після чого стан БД був синхронізований з Alembic через stamp. Для нового чистого запуску достатньо виконати:
docker compose run --rm core alembic -c alembic/alembic.ini upgrade headРеалізовано:
- прийом лідів через
landings - JWT Bearer авторизацію
- перевірку affiliate по токену
- передачу лідів через Redis
- фонову обробку лідів воркером
- дедуплікацію за 10 хвилин
- запис лідів у PostgreSQL
- аналітику по даті та офферу через
core