Skip to content

Commit

Permalink
Fix if in get latest version.
Browse files Browse the repository at this point in the history
Fix join.
Add version parameter to all public endpoints.
  • Loading branch information
Andrey committed Nov 20, 2023
1 parent 0eb6c3e commit de2afed
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 36 deletions.
84 changes: 67 additions & 17 deletions engineapi/engineapi/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
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
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -1006,6 +1028,7 @@ def get_leaderboard_info(
leaderboard_id=leaderboard_id,
version_number=version_number,
)

leaderboard = (
db_session.query(
Leaderboard.id,
Expand All @@ -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(
Expand All @@ -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

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion engineapi/engineapi/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,5 +452,5 @@ class LeaderboardVersion(BaseModel):
updated_at: datetime


class LeaderboardVersionUpdateRequest(BaseModel):
class LeaderboardVersionRequest(BaseModel):
publish: bool
55 changes: 37 additions & 18 deletions engineapi/engineapi/routes/leaderboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
"""
Expand All @@ -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)

Expand All @@ -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,
Expand Down Expand Up @@ -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.
Expand All @@ -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.")
Expand Down Expand Up @@ -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]:
"""
Expand All @@ -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 = [
Expand All @@ -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]:
"""
Expand All @@ -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(
Expand All @@ -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]:
"""
Expand All @@ -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,
Expand Down Expand Up @@ -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:
"""
Expand All @@ -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(
Expand All @@ -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.",
),
Expand Down

0 comments on commit de2afed

Please sign in to comment.