fix docker scraping

improve batch sync

add postgres upsert

fix sync locking

improve listing sync

speed up scraper

clean up project

prepare for github

update docker setup
This commit is contained in:
qananasikq
2026-04-13 16:35:08 +03:00
parent b9557922ed
commit a4c93a1df1
30 changed files with 2239 additions and 624 deletions

View File

@@ -1,9 +1,4 @@
"""Initial schema — cars, images, sync_runs
Revision ID: 001_initial
Revises:
Create Date: 2026-04-08
"""
# Начальная схема: cars, images, sync_runs
from typing import Sequence, Union
from alembic import op
@@ -16,7 +11,7 @@ depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# --- cars ---
# Таблица cars — аукционные машины с IAAI
op.create_table(
"cars",
sa.Column("id", sa.BigInteger, primary_key=True, autoincrement=True),
@@ -53,7 +48,7 @@ def upgrade() -> None:
op.create_index("ix_cars_origin_url", "cars", ["origin_url"])
op.create_index("ix_cars_origin_id", "cars", ["origin_id"], unique=True)
# --- images ---
# Таблица images — изображения машин
op.create_table(
"images",
sa.Column("id", sa.BigInteger, primary_key=True, autoincrement=True),
@@ -63,7 +58,7 @@ def upgrade() -> None:
sa.Column("car_id", sa.Integer, sa.ForeignKey("cars.id", ondelete="CASCADE"), nullable=False),
)
# --- sync_runs ---
# Таблица sync_runs — логирование синхронизаций
op.create_table(
"sync_runs",
sa.Column("id", sa.BigInteger, primary_key=True, autoincrement=True),

View File

@@ -1,9 +1,4 @@
"""Add performance indexes for growing database
Revision ID: 002_add_indexes
Revises: 001_initial
Create Date: 2026-04-09
"""
# Индексы производительности
from typing import Sequence, Union
from alembic import op
@@ -15,25 +10,12 @@ depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# cars: ускорение фильтрации по бренду в API и статистике
op.create_index("ix_cars_brand", "cars", ["brand"])
# cars: составной индекс бренд+модель для комбинированных фильтров
op.create_index("ix_cars_brand_model", "cars", ["brand", "model"])
# cars: ускорение фильтрации по году (year_min/year_max)
op.create_index("ix_cars_year", "cars", ["year"])
# cars: ускорение фильтрации по статусу продажи
op.create_index("ix_cars_is_sold", "cars", ["is_sold"])
# cars: ускорение сортировки ORDER BY last_seen_at DESC (пагинация)
op.create_index("ix_cars_last_seen_at", "cars", ["last_seen_at"])
# images: ускорение JOIN/DELETE по car_id (критично при upsert)
op.create_index("ix_images_car_id", "images", ["car_id"])
# sync_runs: ускорение поиска stale runs по статусу
op.create_index("ix_sync_runs_status", "sync_runs", ["status"])

View File

@@ -0,0 +1,38 @@
# Индексы для масштабированной БД (20k+ записей)
from typing import Sequence, Union
from alembic import op
revision: str = "003_add_composite_indexes"
down_revision: Union[str, None] = "002_add_indexes"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# Partial index для активных машин IAAI (is_sold = FALSE)
# Ускоряет поиск при mark_sold операциях
op.execute(
"CREATE INDEX IF NOT EXISTS ix_cars_active_iaai "
"ON cars (origin_url) "
"WHERE is_sold = FALSE AND origin_id LIKE 'iaai:%'"
)
# Composite index для проверки дубликатов изображений
op.create_index(
"ix_images_car_id_fullres",
"images",
["car_id", "fullres_image"],
)
# Index для быстрого поиска existing машин по origin_url
op.execute(
"CREATE INDEX IF NOT EXISTS ix_cars_origin_url_id "
"ON cars (origin_url, origin_id)"
)
def downgrade() -> None:
op.execute("DROP INDEX IF EXISTS ix_cars_origin_url_id")
op.drop_index("ix_images_car_id_fullres", table_name="images")
op.execute("DROP INDEX IF EXISTS ix_cars_active_iaai")