krz/hutch-stats

Server-side utility for calculating contributions for sourcehut users.

clone: git clone https://gitbay.org/krz/hutch-stats.git

main: src/srht_contrib/models.py · raw

  1from __future__ import annotations
  2
  3from datetime import datetime
  4
  5from sqlalchemy import JSON, Boolean, DateTime, Float, Index, Integer, String, Text, UniqueConstraint
  6from sqlalchemy.orm import Mapped, mapped_column
  7
  8from srht_contrib.db import Base
  9
 10
 11class ContributionEvent(Base):
 12    __tablename__ = "contribution_events"
 13    __table_args__ = (
 14        UniqueConstraint("service", "external_uid", name="uq_contribution_event_service_uid"),
 15        Index("ix_contribution_events_actor_occurred_at", "actor", "occurred_at"),
 16        Index("ix_contribution_events_service_occurred_at", "service", "occurred_at"),
 17    )
 18
 19    id: Mapped[int] = mapped_column(Integer, primary_key=True)
 20    service: Mapped[str] = mapped_column(String(32), nullable=False)
 21    event_type: Mapped[str] = mapped_column(String(64), nullable=False)
 22    actor: Mapped[str] = mapped_column(String(255), nullable=False)
 23    repo_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
 24    resource_id: Mapped[str] = mapped_column(String(255), nullable=False)
 25    external_uid: Mapped[str] = mapped_column(String(255), nullable=False)
 26    occurred_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
 27    weight: Mapped[float] = mapped_column(Float, nullable=False)
 28    raw_payload_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
 29
 30
 31class SyncState(Base):
 32    __tablename__ = "sync_states"
 33    __table_args__ = (UniqueConstraint("service", "actor", name="uq_sync_state_service_actor"),)
 34
 35    id: Mapped[int] = mapped_column(Integer, primary_key=True)
 36    service: Mapped[str] = mapped_column(String(32), nullable=False)
 37    actor: Mapped[str] = mapped_column(String(255), nullable=False)
 38    cursor_value: Mapped[str | None] = mapped_column(Text, nullable=True)
 39    updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
 40
 41
 42class TrackedRepository(Base):
 43    __tablename__ = "tracked_repositories"
 44    __table_args__ = (
 45        UniqueConstraint("service", "actor", "repo_name", name="uq_tracked_repository_service_actor_name"),
 46    )
 47
 48    id: Mapped[int] = mapped_column(Integer, primary_key=True)
 49    service: Mapped[str] = mapped_column(String(32), nullable=False)
 50    repo_name: Mapped[str] = mapped_column(String(255), nullable=False)
 51    actor: Mapped[str] = mapped_column(String(255), nullable=False)
 52
 53
 54class ActorAlias(Base):
 55    __tablename__ = "actor_aliases"
 56    __table_args__ = (UniqueConstraint("alias", name="uq_actor_alias_alias"),)
 57
 58    id: Mapped[int] = mapped_column(Integer, primary_key=True)
 59    canonical_actor: Mapped[str] = mapped_column(String(255), nullable=False)
 60    alias: Mapped[str] = mapped_column(String(255), nullable=False)
 61
 62
 63class TrackedActor(Base):
 64    __tablename__ = "tracked_actors"
 65    __table_args__ = (UniqueConstraint("actor", name="uq_tracked_actor_actor"),)
 66
 67    id: Mapped[int] = mapped_column(Integer, primary_key=True)
 68    actor: Mapped[str] = mapped_column(String(255), nullable=False)
 69    is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
 70    discovery_state: Mapped[str] = mapped_column(String(32), nullable=False, default="queued")
 71    queued_for_discovery_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
 72    priority_boosted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
 73    next_poll_after: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
 74    last_claimed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
 75    poll_attempts: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
 76    last_requested_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
 77    last_polled_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
 78    last_poll_status: Mapped[str | None] = mapped_column(String(32), nullable=True)
 79    last_poll_error: Mapped[str | None] = mapped_column(Text, nullable=True)
 80    recent_backfill_status: Mapped[str] = mapped_column(String(32), nullable=False, default="pending")
 81    recent_backfill_started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
 82    recent_backfill_completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
 83    last_recent_backfill_error: Mapped[str | None] = mapped_column(Text, nullable=True)
 84    backfill_status: Mapped[str] = mapped_column(String(32), nullable=False, default="pending")
 85    backfill_started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
 86    backfill_completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
 87    last_backfill_error: Mapped[str | None] = mapped_column(Text, nullable=True)
 88
 89
 90class DiscoveredRepository(Base):
 91    __tablename__ = "discovered_repositories"
 92    __table_args__ = (UniqueConstraint("actor", "name", name="uq_discovered_repository_actor_name"),)
 93
 94    id: Mapped[int] = mapped_column(Integer, primary_key=True)
 95    actor: Mapped[str] = mapped_column(String(255), nullable=False)
 96    name: Mapped[str] = mapped_column(String(255), nullable=False)
 97    discovered_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
 98
 99
100class ServiceBackfillState(Base):
101    __tablename__ = "service_backfill_states"
102    __table_args__ = (UniqueConstraint("actor", "service", "scope", name="uq_service_backfill_state_actor_service_scope"),)
103
104    id: Mapped[int] = mapped_column(Integer, primary_key=True)
105    actor: Mapped[str] = mapped_column(String(255), nullable=False)
106    service: Mapped[str] = mapped_column(String(32), nullable=False)
107    scope: Mapped[str] = mapped_column(String(16), nullable=False, default="full")
108    cursor_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)
109    status: Mapped[str] = mapped_column(String(32), nullable=False, default="pending")
110    started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
111    completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
112    last_error: Mapped[str | None] = mapped_column(Text, nullable=True)
113    updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)