Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(convert): add file_map table to return correct hash, and jacket conversion task #41

Merged
merged 11 commits into from
Jul 2, 2022
Prev Previous commit
Next Next commit
Revert: Reformat all
sevenc-nanashi committed Jun 16, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 384f50757fad6812f0538945efcfbd6eb54b525d
7 changes: 3 additions & 4 deletions alembic/versions/dcb059ce5b46_add_process_table.py
Original file line number Diff line number Diff line change
@@ -5,13 +5,12 @@
Create Date: 2022-06-12 19:09:48.636469

"""
from alembic import op
import sqlalchemy as sa

from alembic import op

# revision identifiers, used by Alembic.
revision = 'dcb059ce5b46'
down_revision = '21e5008f643b'
revision = "dcb059ce5b46"
down_revision = "21e5008f643b"
branch_labels = None
depends_on = None

46 changes: 34 additions & 12 deletions src/cruds/defaults/level.py
Original file line number Diff line number Diff line change
@@ -22,9 +22,9 @@
from src.cruds.utils.funcs import remove_prefix
from src.cruds.utils.search import buildDatabaseQuery
from src.database.objects.background import Background as BackgroundSave
from src.database.objects.file_map import FileMap
from src.database.objects.effect import Effect as EffectSave
from src.database.objects.engine import Engine as EngineSave
from src.database.objects.file_map import FileMap
from src.database.objects.genre import Genre as GenreSave
from src.database.objects.level import Level as LevelSave
from src.database.objects.particle import Particle as ParticleSave
@@ -57,7 +57,9 @@ class SRLConvert:


class LevelCrud(AbstractCrud): # type: ignore
async def create_dict(self, db: AsyncSession, model: LevelReqResp, exclude_unset: bool = False) -> Dict[str, Any]:
async def create_dict(
self, db: AsyncSession, model: LevelReqResp, exclude_unset: bool = False
) -> Dict[str, Any]:
"""モデルに指定されたSonolusオブジェクトをDBから取り出してIDを埋めます"""
model_import: Dict[str, Any] = model.dict(exclude_unset=exclude_unset)
# DB側カラム名に合わせる
@@ -70,15 +72,21 @@ async def create_dict(self, db: AsyncSession, model: LevelReqResp, exclude_unset
if convert.name in model_import:
obj_req = model_import[convert.name]
if obj_req:
obj_db = await get_first_item_or_404(db, select(convert.obj.id).filter(convert.obj.name == obj_req))
obj_db = await get_first_item_or_404(
db, select(convert.obj.id).filter(convert.obj.name == obj_req)
)
model_import[convert.name + "Id"] = obj_db
# 存在してると変換できないフィールドを消す
for key in ["artists", "artistsEn", "preview"] + [s.name for s in SRLConvertDict]:
for key in ["artists", "artistsEn", "preview"] + [
s.name for s in SRLConvertDict
]:
if key in model_import:
del model_import[key]
return model_import

async def bulk_db_to_resp(self, db: AsyncSession, level_db: LevelSave, localization: str = "ja") -> None:
async def bulk_db_to_resp(
self, db: AsyncSession, level_db: LevelSave, localization: str = "ja"
) -> None:
# 各地のSRLを応答型に変換し回る
for db_obj in [
level_db,
@@ -104,9 +112,13 @@ async def get_named_item_or_404(self, db: AsyncSession, name: str) -> LevelReqRe
stmt.options(
joinedload(LevelSave.engine).options(
joinedload(EngineSave.user),
joinedload(EngineSave.background).options(joinedload(BackgroundSave.user)),
joinedload(EngineSave.background).options(
joinedload(BackgroundSave.user)
),
joinedload(EngineSave.skin).options(joinedload(SkinSave.user)),
joinedload(EngineSave.particle).options(joinedload(ParticleSave.user)),
joinedload(EngineSave.particle).options(
joinedload(ParticleSave.user)
),
joinedload(EngineSave.effect).options(joinedload(EffectSave.user)),
),
joinedload(LevelSave.genre),
@@ -148,7 +160,9 @@ async def add(
)
return resp

async def get(self, db: AsyncSession, name: str, localization: str) -> GetLevelResponse:
async def get(
self, db: AsyncSession, name: str, localization: str
) -> GetLevelResponse:
"""レベルを取得します"""
level_db = await self.get_named_item_or_404(db, remove_prefix(name))
await self.bulk_db_to_resp(db, level_db, localization)
@@ -192,17 +206,23 @@ async def delete(
await super().delete(db, name, auth)
return None

async def list(self, db: AsyncSession, page: int, queries: SearchQueries) -> GetLevelListResponse:
async def list(
self, db: AsyncSession, page: int, queries: SearchQueries
) -> GetLevelListResponse:
"""レベル一覧を取得します"""
select_query = buildDatabaseQuery(LevelSave, queries, False)
userPage: Page[LevelSave] = await paginate(
db,
select_query.options(
selectinload(LevelSave.engine).options(
joinedload(EngineSave.user),
joinedload(EngineSave.background).options(joinedload(BackgroundSave.user)),
joinedload(EngineSave.background).options(
joinedload(BackgroundSave.user)
),
joinedload(EngineSave.skin).options(joinedload(SkinSave.user)),
joinedload(EngineSave.particle).options(joinedload(ParticleSave.user)),
joinedload(EngineSave.particle).options(
joinedload(ParticleSave.user)
),
joinedload(EngineSave.effect).options(joinedload(EffectSave.user)),
),
joinedload(LevelSave.genre),
@@ -213,7 +233,9 @@ async def list(self, db: AsyncSession, page: int, queries: SearchQueries) -> Get
Params(page=page + 1, size=20),
) # type: ignore
resp: SonolusPage = toSonolusPage(userPage)
await asyncio.gather(*[self.bulk_db_to_resp(db, r, queries.localization) for r in resp.items])
await asyncio.gather(
*[self.bulk_db_to_resp(db, r, queries.localization) for r in resp.items]
)
resp.items = [r.toItem() for r in resp.items]
return GetLevelListResponse(
pageCount=resp.pageCount if resp.pageCount > 0 else 1,
2 changes: 1 addition & 1 deletion src/cruds/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@
get_first_item,
get_first_item_or_403,
get_first_item_or_404,
get_first_item_wait_or_404,
get_first_item_or_error,
get_first_item_wait_or_404,
get_new_name,
is_exist,
not_exist_or_409,
22 changes: 15 additions & 7 deletions src/cruds/utils/db.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import ABCMeta
import asyncio
from abc import ABCMeta
from typing import Any, Optional, TypeVar

from fastapi import HTTPException
@@ -35,7 +35,9 @@ def get_first_item(db: AsyncSession, statement: Any) -> Optional[T]:
return obj_db


async def get_first_item_or_error(db: AsyncSession, statement: Any, error: HTTPException) -> T:
async def get_first_item_or_error(
db: AsyncSession, statement: Any, error: HTTPException
) -> T:
"""データベースに指定された要素が存在すれば取得、なければエラー"""
resp: Result = await db.execute(statement)
obj_db: Optional[T] = resp.scalars().first()
@@ -52,7 +54,9 @@ async def get_first_item_or_404(
resp: T = await get_first_item_or_error(
db,
statement,
HTTPException(status_code=404, detail="Specified content was not found on server"),
HTTPException(
status_code=404, detail="Specified content was not found on server"
),
)
return resp

@@ -62,7 +66,9 @@ async def get_first_item_or_403(
statement: Any,
) -> T:
"""データベースに指定された要素が存在すれば取得、なければ Forbidden"""
resp: T = await get_first_item_or_error(db, statement, HTTPException(status_code=403, detail="Forbidden"))
resp: T = await get_first_item_or_error(
db, statement, HTTPException(status_code=403, detail="Forbidden")
)
return resp


@@ -77,12 +83,14 @@ async def get_first_item_wait_or_404(
return await get_first_item_or_error(
db,
statement,
AssertionError,
HTTPException(404),
)
except AssertionError:
except HTTPException:
await asyncio.sleep(1)
else:
raise HTTPException(status_code=400, detail="Specified content was not found on server")
raise HTTPException(
status_code=404, detail="Specified content was not found on server"
)


async def not_exist_or_409(db: AsyncSession, statement: Any) -> None:
7 changes: 5 additions & 2 deletions src/tasks/image_process.py
Original file line number Diff line number Diff line change
@@ -47,7 +47,9 @@ class ImageProcessTask:
hash: str
user_display_id: str

def __init__(self, db: AsyncSession, type_: str, hash: str, user_display_id: str) -> None:
def __init__(
self, db: AsyncSession, type_: str, hash: str, user_display_id: str
) -> None:
self.status = ImageProcessStatus.PROCESSING
self.db = db
self.type = type_
@@ -60,7 +62,8 @@ async def __call__(self) -> None:
try:
async with httpx.AsyncClient() as client:
resp = await client.post(
f"{IMAGE_SERVICE_ENDPOINT}/convert", json={"type": self.type, "hash": self.hash}
f"{IMAGE_SERVICE_ENDPOINT}/convert",
json={"type": self.type, "hash": self.hash},
)
# 連携先がエラーを吐くと LevelConversionException
if resp.status_code != 200: