Fix if in get latest version.

Fix join.
Add version parameter to all public endpoints.
pull/966/head
Andrey 2023-11-20 15:34:47 +02:00
rodzic 0eb6c3e2b9
commit de2afed559
3 zmienionych plików z 105 dodań i 36 usunięć

Wyświetl plik

@ -11,7 +11,7 @@ from hexbytes import HexBytes
import requests # type: ignore
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.orm import Session
from sqlalchemy import func, text, or_, Subquery
from sqlalchemy import func, text, or_, and_, Subquery
from sqlalchemy.engine import Row
from web3 import Web3
from web3.types import ChecksumAddress
@ -970,7 +970,7 @@ def leaderboard_version_filter(
version_number: Optional[int] = None,
) -> Union[Subquery, int]:
# Subquery to get the latest version number for the given leaderboard
if not version_number:
if version_number is None:
latest_version = (
db_session.query(func.max(LeaderboardVersion.version_number)).filter(
LeaderboardVersion.leaderboard_id == leaderboard_id,
@ -983,16 +983,38 @@ def leaderboard_version_filter(
return latest_version
def get_leaderboard_total_count(db_session: Session, leaderboard_id) -> int:
def get_leaderboard_total_count(
db_session: Session, leaderboard_id, version_number: Optional[int] = None
) -> int:
"""
Get the total number of claimants in the leaderboard
Get the total number of position in the leaderboard
"""
return (
db_session.query(LeaderboardScores)
.filter(LeaderboardScores.leaderboard_id == leaderboard_id)
.count()
latest_version = leaderboard_version_filter(
db_session=db_session,
leaderboard_id=leaderboard_id,
version_number=version_number,
)
total_count = (
db_session.query(func.count(LeaderboardScores.id))
.join(
LeaderboardVersion,
and_(
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
LeaderboardVersion.version_number
== LeaderboardScores.leaderboard_version_number,
),
)
.filter(
LeaderboardVersion.published == True,
LeaderboardVersion.version_number == latest_version,
)
.filter(LeaderboardScores.leaderboard_id == leaderboard_id)
).scalar()
return total_count
def get_leaderboard_info(
db_session: Session, leaderboard_id: uuid.UUID, version_number: Optional[int] = None
@ -1006,6 +1028,7 @@ def get_leaderboard_info(
leaderboard_id=leaderboard_id,
version_number=version_number,
)
leaderboard = (
db_session.query(
Leaderboard.id,
@ -1021,7 +1044,11 @@ def get_leaderboard_info(
)
.join(
LeaderboardVersion,
LeaderboardVersion.leaderboard_id == Leaderboard.id,
and_(
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
LeaderboardVersion.version_number
== LeaderboardScores.leaderboard_version_number,
),
isouter=True,
)
.filter(
@ -1030,8 +1057,7 @@ def get_leaderboard_info(
)
.filter(Leaderboard.id == leaderboard_id)
.group_by(Leaderboard.id, Leaderboard.title, Leaderboard.description)
.one()
)
).one()
return leaderboard
@ -1146,7 +1172,11 @@ def get_position(
)
.join(
LeaderboardVersion,
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
and_(
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
LeaderboardVersion.version_number
== LeaderboardScores.leaderboard_version_number,
),
)
.filter(
LeaderboardVersion.published == True,
@ -1222,7 +1252,11 @@ def get_leaderboard_positions(
)
.join(
LeaderboardVersion,
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
and_(
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
LeaderboardVersion.version_number
== LeaderboardScores.leaderboard_version_number,
),
)
.filter(LeaderboardScores.leaderboard_id == leaderboard_id)
.filter(LeaderboardVersion.published == True)
@ -1260,7 +1294,11 @@ def get_qurtiles(
)
.join(
LeaderboardVersion,
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
and_(
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
LeaderboardVersion.version_number
== LeaderboardScores.leaderboard_version_number,
),
)
.filter(
LeaderboardVersion.published == True,
@ -1314,7 +1352,11 @@ def get_ranks(
)
.join(
LeaderboardVersion,
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
and_(
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
LeaderboardVersion.version_number
== LeaderboardScores.leaderboard_version_number,
),
)
.filter(
LeaderboardVersion.published == True,
@ -1361,7 +1403,11 @@ def get_rank(
)
.join(
LeaderboardVersion,
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
and_(
LeaderboardVersion.leaderboard_id == LeaderboardScores.leaderboard_id,
LeaderboardVersion.version_number
== LeaderboardScores.leaderboard_version_number,
),
)
.filter(
LeaderboardVersion.published == True,
@ -1546,7 +1592,11 @@ def add_scores(
insert_statement = insert(LeaderboardScores).values(leaderboard_scores)
result_stmt = insert_statement.on_conflict_do_update(
index_elements=[LeaderboardScores.address, LeaderboardScores.leaderboard_id],
index_elements=[
LeaderboardScores.address,
LeaderboardScores.leaderboard_id,
LeaderboardScores.leaderboard_version_number,
],
set_=dict(
score=insert_statement.excluded.score,
points_data=insert_statement.excluded.points_data,

Wyświetl plik

@ -452,5 +452,5 @@ class LeaderboardVersion(BaseModel):
updated_at: datetime
class LeaderboardVersionUpdateRequest(BaseModel):
class LeaderboardVersionRequest(BaseModel):
publish: bool

Wyświetl plik

@ -355,6 +355,7 @@ async def get_leaderboards(
)
async def count_addresses(
leaderboard_id: UUID = Query(..., description="Leaderboard ID"),
version: Optional[int] = Query(None, description="Version of the leaderboard."),
db_session: Session = Depends(db.yield_db_session),
) -> data.CountAddressesResponse:
"""
@ -373,7 +374,7 @@ async def count_addresses(
logger.error(f"Error while getting leaderboard: {e}")
raise EngineHTTPException(status_code=500, detail="Internal server error")
count = actions.get_leaderboard_total_count(db_session, leaderboard_id)
count = actions.get_leaderboard_total_count(db_session, leaderboard_id, version)
return data.CountAddressesResponse(count=count)
@ -384,12 +385,13 @@ async def count_addresses(
async def leadeboard_info(
leaderboard_id: UUID = Query(..., description="Leaderboard ID"),
db_session: Session = Depends(db.yield_db_session),
version: Optional[int] = Query(None, description="Version of the leaderboard."),
) -> data.LeaderboardInfoResponse:
"""
Returns leaderboard info.
"""
try:
leaderboard = actions.get_leaderboard_info(db_session, leaderboard_id)
leaderboard = actions.get_leaderboard_info(db_session, leaderboard_id, version)
except NoResultFound as e:
raise EngineHTTPException(
status_code=404,
@ -443,6 +445,7 @@ async def get_scores_changes(
async def quartiles(
leaderboard_id: UUID = Query(..., description="Leaderboard ID"),
db_session: Session = Depends(db.yield_db_session),
version: Optional[int] = Query(None, description="Version of the leaderboard."),
) -> data.QuartilesResponse:
"""
Returns the quartiles of the leaderboard.
@ -460,7 +463,7 @@ async def quartiles(
raise EngineHTTPException(status_code=500, detail="Internal server error")
try:
q1, q2, q3 = actions.get_qurtiles(db_session, leaderboard_id)
q1, q2, q3 = actions.get_qurtiles(db_session, leaderboard_id, version)
except actions.LeaderboardIsEmpty:
raise EngineHTTPException(status_code=204, detail="Leaderboard is empty.")
@ -489,6 +492,7 @@ async def position(
normalize_addresses: bool = Query(
True, description="Normalize addresses to checksum."
),
version: Optional[int] = Query(None, description="Version of the leaderboard."),
db_session: Session = Depends(db.yield_db_session),
) -> List[data.LeaderboardPosition]:
"""
@ -512,7 +516,13 @@ async def position(
address = Web3.toChecksumAddress(address)
positions = actions.get_position(
db_session, leaderboard_id, address, window_size, limit, offset
db_session,
leaderboard_id,
address,
window_size,
limit,
offset,
version,
)
results = [
@ -536,6 +546,7 @@ async def rank(
rank: int = Query(1, description="Rank to get."),
limit: Optional[int] = Query(None),
offset: Optional[int] = Query(None),
version: Optional[int] = Query(None, description="Version of the leaderboard."),
db_session: Session = Depends(db.yield_db_session),
) -> List[data.LeaderboardPosition]:
"""
@ -555,7 +566,12 @@ async def rank(
raise EngineHTTPException(status_code=500, detail="Internal server error")
leaderboard_rank = actions.get_rank(
db_session, leaderboard_id, rank, limit=limit, offset=offset
db_session,
leaderboard_id,
rank,
limit=limit,
offset=offset,
version_number=version,
)
results = [
data.LeaderboardPosition(
@ -572,6 +588,7 @@ async def rank(
@app.get("/ranks", response_model=List[data.RanksResponse], tags=["Public Endpoints"])
async def ranks(
leaderboard_id: UUID = Query(..., description="Leaderboard ID"),
version: Optional[int] = Query(None, description="Version of the leaderboard."),
db_session: Session = Depends(db.yield_db_session),
) -> List[data.RanksResponse]:
"""
@ -590,7 +607,7 @@ async def ranks(
logger.error(f"Error while getting leaderboard: {e}")
raise EngineHTTPException(status_code=500, detail="Internal server error")
ranks = actions.get_ranks(db_session, leaderboard_id)
ranks = actions.get_ranks(db_session, leaderboard_id, version)
results = [
data.RanksResponse(
score=rank.score,
@ -1038,8 +1055,11 @@ async def leaderboard_version_handler(
async def create_leaderboard_version(
request: Request,
leaderboard_id: UUID = Path(..., description="Leaderboard ID"),
version: int = Query(..., description="Version of the leaderboard."),
db_session: Session = Depends(db.yield_db_session),
request_body: data.LeaderboardVersionRequest = Body(
...,
description="JSON object specifying whether to publish or unpublish version.",
),
Authorization: str = AuthHeader,
) -> data.LeaderboardVersion:
"""
@ -1064,23 +1084,22 @@ async def create_leaderboard_version(
)
try:
leaderboard_version = actions.create_leaderboard_version(
new_version = actions.create_leaderboard_version(
db_session=db_session,
leaderboard_id=leaderboard_id,
version=version,
)
except BugoutResponseException as e:
raise EngineHTTPException(status_code=e.status_code, detail=e.detail)
except actions.LeaderboardConfigNotFound as e:
raise EngineHTTPException(
status_code=404,
detail="Leaderboard config not found.",
publish=request_body.publish,
)
except Exception as e:
logger.error(f"Error while creating leaderboard version: {e}")
raise EngineHTTPException(status_code=500, detail="Internal server error")
return leaderboard_version
return data.LeaderboardVersion(
leaderboard_id=new_version.leaderboard_id,
version=new_version.version_number,
published=new_version.published,
created_at=new_version.created_at,
updated_at=new_version.updated_at,
)
@app.put(
@ -1092,7 +1111,7 @@ async def update_leaderboard_version_handler(
request: Request,
leaderboard_id: UUID = Path(..., description="Leaderboard ID"),
version: int = Path(..., description="Version of the leaderboard."),
request_body: data.LeaderboardVersionUpdateRequest = Body(
request_body: data.LeaderboardVersionRequest = Body(
...,
description="JSON object specifying whether to publish or unpublish version.",
),