feat(performance-point): switch performance calculator to performance-server (#80)
* feat(config): make `performance_server` as default calculator * deploy(docker): use osu-performance-server * docs(readme): add ruleset download instructions * chore(dev): update development environment * feat(dev): update development environment setup and service startup order * fix(deps): move `rosu-pp-py` to `project.optional-dependencies` * feat(beatmap): handle deleted beatmaps * feat(performance-server): add a long timeout for calculation * feat(recalculate): enhance CLI arguments for performance, leaderboard, and rating recalculations with CSV output support * fix(recalculate): resolve reviews * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix(beatmapsync): resolve too long line --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -83,7 +83,7 @@ class PerformanceServerPerformanceCalculator(BasePerformanceCalculator):
|
||||
|
||||
async def calculate_performance(self, beatmap_raw: str, score: "Score") -> PerformanceAttributes:
|
||||
# https://github.com/GooGuTeam/osu-performance-server#post-performance
|
||||
async with AsyncClient() as client:
|
||||
async with AsyncClient(timeout=15) as client:
|
||||
try:
|
||||
resp = await client.post(
|
||||
f"{self.server_url}/performance",
|
||||
@@ -121,7 +121,7 @@ class PerformanceServerPerformanceCalculator(BasePerformanceCalculator):
|
||||
self, beatmap_raw: str, mods: list[APIMod] | None = None, gamemode: GameMode | None = None
|
||||
) -> DifficultyAttributes:
|
||||
# https://github.com/GooGuTeam/osu-performance-server#post-difficulty
|
||||
async with AsyncClient() as client:
|
||||
async with AsyncClient(timeout=15) as client:
|
||||
try:
|
||||
resp = await client.post(
|
||||
f"{self.server_url}/difficulty",
|
||||
|
||||
@@ -114,14 +114,7 @@ STORAGE_SETTINGS='{
|
||||
""",
|
||||
"表现计算设置": """配置表现分计算器及其参数。
|
||||
|
||||
### rosu-pp-py (默认)
|
||||
|
||||
```bash
|
||||
CALCULATOR="rosu"
|
||||
CALCULATOR_CONFIG='{}'
|
||||
```
|
||||
|
||||
### [osu-performance-server](https://github.com/GooGuTeam/osu-performance-server)
|
||||
### [osu-performance-server](https://github.com/GooGuTeam/osu-performance-server) (默认)
|
||||
|
||||
```bash
|
||||
CALCULATOR="performance_server"
|
||||
@@ -129,6 +122,13 @@ CALCULATOR_CONFIG='{
|
||||
"server_url": "http://localhost:5225"
|
||||
}'
|
||||
```
|
||||
|
||||
### rosu-pp-py
|
||||
|
||||
```bash
|
||||
CALCULATOR="rosu"
|
||||
CALCULATOR_CONFIG='{}'
|
||||
```
|
||||
""",
|
||||
}
|
||||
},
|
||||
@@ -533,13 +533,13 @@ CALCULATOR_CONFIG='{
|
||||
# 表现计算设置
|
||||
calculator: Annotated[
|
||||
Literal["rosu", "performance_server"],
|
||||
Field(default="rosu", description="表现分计算器"),
|
||||
Field(default="performance_server", description="表现分计算器"),
|
||||
"表现计算设置",
|
||||
]
|
||||
calculator_config: Annotated[
|
||||
dict[str, Any],
|
||||
Field(
|
||||
default={},
|
||||
default={"server_url": "http://localhost:5225"},
|
||||
description="表现分计算器配置 (JSON 格式),具体配置项请参考上方",
|
||||
),
|
||||
"表现计算设置",
|
||||
|
||||
@@ -160,6 +160,7 @@ class BeatmapResp(BeatmapBase):
|
||||
failtimes: FailTimeResp | None = None
|
||||
top_tag_ids: list[APIBeatmapTag] | None = None
|
||||
current_user_tag_ids: list[int] | None = None
|
||||
is_deleted: bool = False
|
||||
|
||||
@classmethod
|
||||
async def from_db(
|
||||
@@ -184,6 +185,7 @@ class BeatmapResp(BeatmapBase):
|
||||
beatmap_["status"] = beatmap_status.name.lower()
|
||||
beatmap_["ranked"] = beatmap_status.value
|
||||
beatmap_["mode_int"] = int(beatmap.mode)
|
||||
beatmap_["is_deleted"] = beatmap.deleted_at is not None
|
||||
if not from_set:
|
||||
beatmap_["beatmapset"] = await BeatmapsetResp.from_db(beatmap.beatmapset, session=session, user=user)
|
||||
if beatmap.failtimes is not None:
|
||||
|
||||
@@ -23,11 +23,13 @@ class BeatmapRawFetcher(BaseFetcher):
|
||||
resp = await self._request(req_url)
|
||||
if resp.status_code >= 400:
|
||||
continue
|
||||
if not resp.text:
|
||||
continue
|
||||
return resp.text
|
||||
raise HTTPError("Failed to fetch beatmap")
|
||||
|
||||
async def _request(self, url: str) -> Response:
|
||||
async with AsyncClient() as client:
|
||||
async with AsyncClient(timeout=15) as client:
|
||||
response = await client.get(
|
||||
url,
|
||||
)
|
||||
|
||||
@@ -182,6 +182,7 @@ class BeatmapsetUpdateService:
|
||||
logger.error(f"failed to add missing beatmapset {missing}: {e}")
|
||||
if total > 0:
|
||||
logger.opt(colors=True).info(f"added {total} missing beatmapset")
|
||||
await session.commit()
|
||||
self._adding_missing = False
|
||||
|
||||
async def add(self, beatmapset: BeatmapsetResp, calculate_next_sync: bool = True):
|
||||
@@ -397,7 +398,15 @@ class BeatmapsetUpdateService:
|
||||
existing_beatmap = await session.get(Beatmap, change.beatmap_id)
|
||||
if existing_beatmap:
|
||||
await session.merge(new_db_beatmap)
|
||||
if change.type == BeatmapChangeType.MAP_DELETED:
|
||||
existing_beatmap.deleted_at = utcnow()
|
||||
await session.commit()
|
||||
else:
|
||||
if change.type == BeatmapChangeType.MAP_DELETED:
|
||||
logger.opt(colors=True).warning(
|
||||
f"<g>[beatmap: {change.beatmap_id}]</g> MAP_DELETED received "
|
||||
f"but beatmap not found in database; deletion skipped"
|
||||
)
|
||||
if change.type != BeatmapChangeType.STATUS_CHANGED:
|
||||
await _process_update_or_delete_beatmaps(change.beatmap_id)
|
||||
await get_beatmapset_cache_service(get_redis()).invalidate_beatmap_lookup_cache(change.beatmap_id)
|
||||
|
||||
Reference in New Issue
Block a user