-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from MultiQC/buffer-visits
Summarise visits by minute; buffer in memory and in CSV before DB
- Loading branch information
Showing
6 changed files
with
219 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -138,3 +138,5 @@ dmypy.json | |
.idea/ | ||
|
||
.DS_Store | ||
|
||
visits.csv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
"""api.multiqc.info: Providing run-time information about available updates.""" | ||
|
||
__version__ = "0.1.0.dev0" | ||
|
||
from dotenv import load_dotenv | ||
|
||
load_dotenv() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,51 @@ | ||
"""Functions to interact with the database.""" | ||
import os | ||
|
||
import datetime | ||
from os import getenv | ||
|
||
from sqlmodel import create_engine, Field, select, Session, SQLModel | ||
|
||
sql_url = getenv("DATABASE_URL") | ||
sql_url = os.getenv("DATABASE_URL") | ||
assert sql_url is not None, sql_url | ||
engine = create_engine(sql_url) | ||
|
||
|
||
class Visit(SQLModel, table=True): # type: ignore # mypy doesn't like this, not sure why | ||
"""Table to record raw individual visits to the version endpoint.""" | ||
class Visits(SQLModel, table=True): # type: ignore # mypy doesn't like this, not sure why | ||
""" | ||
Table to record per-minute visit summaries. | ||
Start is a primary key, and start and end are both indexed. | ||
""" | ||
|
||
id: int | None = Field(default=None, primary_key=True) | ||
version_multiqc: str | None = None | ||
version_python: str | None = None | ||
operating_system: str | None = None | ||
installation_method: str | None = None | ||
ci_environment: str | None = None | ||
called_at: datetime.datetime | None = Field(default_factory=datetime.datetime.utcnow, nullable=False) | ||
start: datetime.datetime = Field(primary_key=True) | ||
end: datetime.datetime = Field(primary_key=True) | ||
count: int | ||
version_multiqc: str = Field(index=True) | ||
version_python: str = Field(default=None, index=True) | ||
operating_system: str = Field(default=None, index=True) | ||
installation_method: str = Field(default=None, index=True) | ||
ci_environment: str = Field(default=None, index=True) | ||
|
||
|
||
def create_db_and_tables() -> None: | ||
"""Create the database and tables if they don't exist.""" | ||
SQLModel.metadata.create_all(engine) | ||
|
||
|
||
def add_visit(visit: Visit) -> None: | ||
"""Add a visit to the database.""" | ||
with Session(engine) as session: | ||
session.add(visit) | ||
session.commit() | ||
|
||
|
||
def get_visits( | ||
start: datetime.datetime | None = None, | ||
end: datetime.datetime | None = None, | ||
limit: int | None = None, | ||
) -> list[Visit]: | ||
"""Return list of raw visits from the DB.""" | ||
) -> list[Visits]: | ||
"""Return list of per-minute visit summary from the DB.""" | ||
with Session(engine) as session: | ||
statement = select(Visit) | ||
statement = select(Visits) | ||
if start: | ||
# Ignore type because Visit.called_at can be None for default value | ||
statement.where(Visit.called_at > start) # type: ignore | ||
statement.where(Visits.start >= start) # type: ignore | ||
if end: | ||
statement.where(Visit.called_at < end) # type: ignore | ||
statement.where(Visits.end <= end) # type: ignore | ||
if limit: | ||
statement.limit(limit) | ||
statement.order_by(Visit.called_at.desc()) # type: ignore | ||
statement.order_by(Visits.start.desc()) # type: ignore | ||
return session.exec(statement).all() |
Oops, something went wrong.