Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions plugin_store/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from cdn import upload_image, upload_version
from constants import SortDirection, SortType, TEMPLATES_DIR
from database.database import database, Database
from database.database import database, Database, database_fake, fill_cache
from database.models import Announcement
from discord import post_announcement

Expand Down Expand Up @@ -45,6 +45,9 @@
increment_limit_per_plugin = parse("2/day")
rate_limit = strategies.FixedWindowRateLimiter(rate_limit_storage)

@app.on_event("startup")
async def startup_event():
await fill_cache()

@app.exception_handler(HTTPException)
async def http_exception_handler(request: "Request", exc: "HTTPException") -> "Response":
Expand Down Expand Up @@ -140,18 +143,17 @@ async def delete_announcement(
):
await db.delete_announcement(announcement_id)


@app.get("/plugins", response_model=list[api_list.ListPluginResponse])
async def plugins_list(
query: str = "",
tags: list[str] = fastapi.Query(default=[]),
hidden: bool = False,
sort_by: Optional[SortType] = None,
sort_direction: SortDirection = SortDirection.ASC,
db: "Database" = Depends(database),
sort_direction: SortDirection = SortDirection.DESC,
db: "Database" = Depends(database_fake),
):
tags = list(filter(None, reduce(add, (el.split(",") for el in tags), [])))
plugins = await db.search(db.session, query, tags, hidden, sort_by, sort_direction)
plugins = await db.search(query, hidden, sort_by, sort_direction)
return plugins


Expand Down
49 changes: 42 additions & 7 deletions plugin_store/database/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Optional, TYPE_CHECKING
from uuid import UUID
from zoneinfo import ZoneInfo
from time import time

from alembic import command
from alembic.config import Config
Expand Down Expand Up @@ -39,17 +40,17 @@
AsyncSessionLocal = async_sessionmaker(bind=async_engine, autoflush=False, future=True, expire_on_commit=False)

db_lock = Lock()

plugin_cache = []
last_time = 0

async def get_session() -> "AsyncIterator[AsyncSession]":
try:
yield AsyncSessionLocal()
except SQLAlchemyError as e:
logger.exception(e)


async def database(session: "AsyncSession" = Depends(get_session)) -> "AsyncIterator[Database]":
db = Database(session, db_lock)
db = Database(session, db_lock, plugin_cache)
try:
yield db
except Exception:
Expand All @@ -58,11 +59,23 @@ async def database(session: "AsyncSession" = Depends(get_session)) -> "AsyncIter
else:
await session.close()

async def database_fake() -> "AsyncIterator[Database]":
db = Database(None, db_lock, plugin_cache)
try:
yield db
except Exception:
raise

async def fill_cache():
db = Database(AsyncSessionLocal(), db_lock, plugin_cache)
await db.update_cache(db.session)
await db.session.close()

class Database:
def __init__(self, session, lock):
def __init__(self, session, lock, plugin_cache):
self.session = session
self.lock = lock
self.plugin_cache: list = plugin_cache

@sync_to_async()
def init(self):
Expand Down Expand Up @@ -166,6 +179,7 @@ async def insert_artifact(
await nested.rollback()
raise
await session.commit()
await self.update_cache(session)
return await self.get_plugin_by_id(session, plugin.id)

async def update_artifact(self, session: "AsyncSession", plugin: "Artifact", **kwargs) -> "Artifact":
Expand All @@ -185,6 +199,7 @@ async def update_artifact(self, session: "AsyncSession", plugin: "Artifact", **k
await nested.rollback()
raise
await session.commit()
await self.update_cache(session)
return await self.get_plugin_by_id(session, plugin.id)

async def insert_version(
Expand All @@ -201,7 +216,7 @@ async def insert_version(
await session.commit()
return version

async def search(
async def _search(
self,
session: "AsyncSession",
name: "str | None" = None,
Expand Down Expand Up @@ -237,6 +252,21 @@ async def search(

result = (await session.execute(statement)).scalars().all()
return result or []

async def update_cache(self, session):
self.plugin_cache.clear()
self.plugin_cache.extend(await self._search(session, limit=500, include_hidden=True))

async def search(
self,
name: "str | None" = "",
include_hidden: "bool" = False,
sort_by: Optional[SortType] = None,
sort_direction: SortDirection = SortDirection.DESC
) -> "Sequence[Artifact]":
sort_key = {SortType.NAME: "name", SortType.DOWNLOADS: "downloads", SortType.DATE: "created", "id": "id"}[sort_by or "id"]
return sorted([i for i in self.plugin_cache if i.visible is not include_hidden and name.lower() in i.name.lower()],
key=lambda x: getattr(x, sort_key), reverse=sort_direction==SortDirection.ASC)

async def get_plugin_by_name(self, session: "AsyncSession", name: str) -> "Artifact | None":
statement = select(Artifact).where(Artifact.name == name)
Expand All @@ -253,7 +283,9 @@ async def delete_plugin(self, session: "AsyncSession", id: int):
await session.execute(delete(PluginTag).where(PluginTag.c.artifact_id == id))
await session.execute(delete(Version).where(Version.artifact_id == id))
await session.execute(delete(Artifact).where(Artifact.id == id))
return await session.commit()
r = await session.commit()
await self.update_cache(session)
return r

async def increment_installs(
self, session: "AsyncSession", plugin_name: str, version_name: str, isUpdate: bool
Expand All @@ -269,4 +301,7 @@ async def increment_installs(
r = await session.execute(statement.where((Version.name == version_name) & (Version.artifact_id == plugin_id)))
await session.commit()
# if rowcount is zero then the version wasn't found
return r.rowcount == 1 # type: ignore[attr-defined]
v = r.rowcount == 1 # type: ignore[attr-defined]
# if v:
# await self.update_cache(session)
return v
Loading