feat(worker): ручной пересчёт метрик через очередь, диагностика шагов и heartbeat

POST /metrics/refresh ставит задачу в sync_job (source=METRICS_JOB) и отвечает 202, пересчёт делает worker; GET /metrics/status отдаёт refreshing и consistent. metric_refresh_log хранит failed_step и step_timings. Источники с needs="tinvest_token" не попадают в расписание без токена, tinvest/moex добавлены в default_schedule. Воркер трогает heartbeat-файл для healthcheck.
This commit is contained in:
Dmitry
2026-09-19 21:54:30 +03:00
parent 989a780f9f
commit 3b3ee4d682
11 changed files with 341 additions and 30 deletions
@@ -0,0 +1,34 @@
"""metric_refresh_log: имя упавшего шага и тайминги шагов
Revision ID: c41e7a9d2b05
Revises: 2bf84b07fd5e
Create Date: 2026-09-19 17:10:00.000000
"""
from __future__ import annotations
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql
revision: str = "c41e7a9d2b05"
down_revision: str | None = "2bf84b07fd5e"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
op.add_column(
"metric_refresh_log", sa.Column("failed_step", sa.String(length=64), nullable=True)
)
op.add_column(
"metric_refresh_log",
sa.Column("step_timings", postgresql.JSONB(astext_type=sa.Text()), nullable=True),
)
def downgrade() -> None:
op.drop_column("metric_refresh_log", "step_timings")
op.drop_column("metric_refresh_log", "failed_step")