Skip to content

Commit

Permalink
set up database models
Browse files Browse the repository at this point in the history
  • Loading branch information
elfkuzco committed Jun 2, 2024
1 parent 8b9a744 commit 51fcabb
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 0 deletions.
3 changes: 3 additions & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies = [
"alembic == 1.13.1",
"fastapi[all] == 0.111.0",
"pydantic == 2.7.2",
"SQLAlchemy == 2.0.30",
]
license = {text = "GPL-3.0-or-later"}
classifiers = [
Expand Down Expand Up @@ -182,6 +183,8 @@ ignore = [
"S603",
# Ignore complexity
"C901", "PLR0911", "PLR0912", "PLR0913", "PLR0915",
# Allow typing.List and typing.Optional in annotations
"UP006", "UP007", "UP035",
]
unfixable = [
# Don't touch unused imports
Expand Down
Empty file.
132 changes: 132 additions & 0 deletions backend/src/backend/db/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
from datetime import datetime
from ipaddress import IPv4Address
from typing import List, Optional
from uuid import UUID

from sqlalchemy import DateTime, Enum, ForeignKey, UniqueConstraint, text
from sqlalchemy.dialects.postgresql import ARRAY, CITEXT, INET
from sqlalchemy.orm import (
DeclarativeBase,
Mapped,
MappedAsDataclass,
mapped_column,
relationship,
)
from sqlalchemy.sql.schema import MetaData

from backend.enums import StatusEnum


class Base(MappedAsDataclass, DeclarativeBase):
# This map details the specific transformation of types between Python and
# PostgreSQL. This is only needed for the case where a specific PostgreSQL
# type has to be used.

type_annotation_map = { # noqa: RUF012
str: CITEXT, # transform Python str to PostgreSQL CITEXT
List[str]: ARRAY(
item_type=CITEXT
), # transform Python List[str] into PostgreSQL Array of strings
datetime: DateTime(
timezone=False
), # transform Python datetime into PostgreSQL Datetime without timezone
IPv4Address: INET, # transform Python IPV4Address into PostgreSQL INET
}

# This metadata specifies some naming conventions that will be used by
# alembic to generate constraints names (indexes, unique constraints, ...)
metadata = MetaData(
naming_convention={
"ix": "ix_%(column_0_label)s",
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s",
}
)
pass


class Country(Base):
__tablename__ = "country"

id: Mapped[UUID] = mapped_column(
init=False, primary_key=True, server_default=text("uuid_generate_v4()")
)
code: Mapped[str]
name: Mapped[str]

worker_id: Mapped[Optional[UUID]] = mapped_column(
ForeignKey("worker.id"), init=False
)
worker: Mapped[Optional["Worker"]] = relationship(
back_populates="countries", init=False
)
mirrors: Mapped[List["Mirror"]] = relationship(
back_populates="country",
init=False,
cascade="all, delete-orphan",
)

__table_args__ = (UniqueConstraint("name", "code"),)


class Mirror(Base):
__tablename__ = "mirror"

base_url: Mapped[str] = mapped_column(primary_key=True)
enabled: Mapped[bool]
# metadata of a mirror from MirroBrain (https://mirrorbrain-docs.readthedocs.io/en/latest/mirrors.html#displaying-details-about-a-mirror)
id: Mapped[Optional[str]]
region: Mapped[Optional[str]]
asn: Mapped[Optional[str]]
score: Mapped[Optional[int]]
latitude: Mapped[Optional[float]]
longitude: Mapped[Optional[float]]
country_only: Mapped[Optional[bool]]
region_only: Mapped[Optional[bool]]
as_only: Mapped[Optional[bool]]
other_countries: Mapped[Optional[List[str]]]

country_code: Mapped[str] = mapped_column(
ForeignKey("country.code"),
init=False,
)
country: Mapped["Country"] = relationship(back_populates="mirrors", init=False)


class Worker(Base):
__tablename__ = "worker"
id: Mapped[UUID] = mapped_column(
init=False, primary_key=True, server_default=text("uuid_generate_v4()")
)
auth_info: Mapped[str]
last_seen: Mapped[Optional[datetime]]
countries: Mapped[List["Country"]] = relationship(
back_populates="worker", init=False
)


class Test(Base):
__tablename__ = "test"
id: Mapped[UUID] = mapped_column(
init=False, primary_key=True, server_default=text("uuid_generate_v4()")
)
requested_on: Mapped[datetime]
started_on: Mapped[Optional[datetime]]
status: Mapped[Optional[StatusEnum]] = mapped_column(
Enum(
native_enum=False,
validate_strings=True,
create_constraint=True,
name="status",
)
)
error: Mapped[Optional[str]]
ip_address: Mapped[Optional[IPv4Address]]
asn: Mapped[Optional[str]]
location: Mapped[Optional[str]]
latency: Mapped[Optional[int]] # milliseconds
download_size: Mapped[Optional[int]] # bytes
duration: Mapped[Optional[int]] # seconds
speed: Mapped[Optional[float]] # bytes per second
7 changes: 7 additions & 0 deletions backend/src/backend/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from enum import Enum


class StatusEnum(Enum):
MISSED = 0
SUCCEEDED = 1
ERRORED = 2

0 comments on commit 51fcabb

Please sign in to comment.