Add a super fast latest release API

This commit is contained in:
rubenwardy 2023-09-12 21:15:55 +01:00
parent 886dec3ffd
commit 83e7701eee
2 changed files with 49 additions and 1 deletions

@ -21,7 +21,7 @@ from typing import List
import flask_sqlalchemy import flask_sqlalchemy
from flask import request, jsonify, current_app, Response from flask import request, jsonify, current_app, Response
from flask_login import current_user, login_required from flask_login import current_user, login_required
from sqlalchemy import and_ from sqlalchemy import and_, or_
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
@ -826,3 +826,46 @@ def collection_view(author, name):
ret = collection.as_dict() ret = collection.as_dict()
ret["items"] = [x.as_dict() for x in items] ret["items"] = [x.as_dict() for x in items]
return jsonify(ret) return jsonify(ret)
@bp.route("/api/updates/")
def updates():
protocol_version = get_int_or_abort(request.args.get("protocol_version"))
minetest_version = request.args.get("engine_version")
if protocol_version or minetest_version:
version = MinetestRelease.get(minetest_version, protocol_version)
else:
version = None
# Subquery to get the latest release for each package
latest_release_query = (db.session.query(
PackageRelease.package_id,
func.max(PackageRelease.id).label('max_release_id'))
.select_from(PackageRelease)
.filter(PackageRelease.approved == True))
if version:
latest_release_query = (latest_release_query
.filter(or_(PackageRelease.min_rel_id == None,
PackageRelease.min_rel_id <= version.id))
.filter(or_(PackageRelease.max_rel_id == None,
PackageRelease.max_rel_id >= version.id)))
latest_release_subquery = (
latest_release_query
.group_by(PackageRelease.package_id)
.subquery()
)
# Get package id and latest release
query = (db.session.query(User.username, Package.name, latest_release_subquery.c.max_release_id)
.select_from(Package)
.join(User, Package.author)
.join(latest_release_subquery, Package.id == latest_release_subquery.c.package_id)
.filter(Package.state == PackageState.APPROVED)).all()
ret = {}
for author_username, package_name, release_id in query:
ret[f"{author_username}/{package_name}"] = release_id
return jsonify(ret)

@ -209,6 +209,11 @@ Supported query parameters:
* `author`: author username * `author`: author username
* `name`: technical name * `name`: technical name
* `type`: `mod`, `game`, or `txp` * `type`: `mod`, `game`, or `txp`
* GET `/api/updates/` (Look-up table)
* Returns a look-up table from package key (`author/name`) to latest release id
* Query arguments
* `protocol_version`: Only show packages supported by this Minetest protocol version.
* `engine_version`: Only show packages supported by this Minetest engine version, eg: `5.3.0`.
* GET `/api/packages/<username>/<name>/releases/` (List) * GET `/api/packages/<username>/<name>/releases/` (List)
* Returns array of release dictionaries, see above, but without package info. * Returns array of release dictionaries, see above, but without package info.
* GET `/api/packages/<username>/<name>/releases/<id>/` (Read) * GET `/api/packages/<username>/<name>/releases/<id>/` (Read)