diff --git a/src/lando/api/legacy/api/diff_warnings.py b/src/lando/api/legacy/api/diff_warnings.py index 64a8417b..8109055b 100644 --- a/src/lando/api/legacy/api/diff_warnings.py +++ b/src/lando/api/legacy/api/diff_warnings.py @@ -15,7 +15,6 @@ from lando.api.legacy.decorators import require_phabricator_api_key from lando.main.models.revision import DiffWarning, DiffWarningStatus -from lando.api.legacy.storage import db logger = logging.getLogger(__name__) @@ -41,15 +40,14 @@ def post(data: dict): type="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400", ) warning = DiffWarning(**data) - db.session.add(warning) - db.session.commit() + warning.save() return warning.serialize(), 201 @require_phabricator_api_key(provide_client=False) def delete(pk: str): """Archive a `DiffWarning` based on provided pk.""" - warning = DiffWarning.query.get(pk) + warning = DiffWarning.objects.get(pk=pk) if not warning: return problem( 400, @@ -58,17 +56,17 @@ def delete(pk: str): type="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400", ) warning.status = DiffWarningStatus.ARCHIVED - db.session.commit() + warning.save() return warning.serialize(), 200 @require_phabricator_api_key(provide_client=False) def get(revision_id: str, diff_id: str, group: str): """Return a list of active revision diff warnings, if any.""" - warnings = DiffWarning.query.filter( - DiffWarning.revision_id == revision_id, - DiffWarning.diff_id == diff_id, - DiffWarning.status == DiffWarningStatus.ACTIVE, - DiffWarning.group == group, + warnings = DiffWarning.objects.filter( + revision_id=revision_id, + diff_id=diff_id, + status=DiffWarningStatus.ACTIVE, + group=group, ) return [w.serialize() for w in warnings], 200 diff --git a/src/lando/api/legacy/api/landing_jobs.py b/src/lando/api/legacy/api/landing_jobs.py index cbca3e51..ccdaeeb2 100644 --- a/src/lando/api/legacy/api/landing_jobs.py +++ b/src/lando/api/legacy/api/landing_jobs.py @@ -8,7 +8,6 @@ from lando.api import auth from lando.main.models.landing_job import LandingJob, LandingJobAction, LandingJobStatus -from lando.api.legacy.storage import db logger = logging.getLogger(__name__) @@ -32,6 +31,7 @@ def put(landing_job_id: str, data: dict): updated (for example, when trying to cancel a job that is already in progress). """ + # TODO: fix this based on locks/etc. landing_job = LandingJob.query.with_for_update().get(landing_job_id) if not landing_job: @@ -61,7 +61,7 @@ def put(landing_job_id: str, data: dict): if landing_job.status in (LandingJobStatus.SUBMITTED, LandingJobStatus.DEFERRED): landing_job.transition_status(LandingJobAction.CANCEL) - db.session.commit() + landing_job.save() return {"id": landing_job.id}, 200 else: raise ProblemException( diff --git a/src/lando/api/legacy/api/stacks.py b/src/lando/api/legacy/api/stacks.py index 6aff49c3..20d1db1d 100644 --- a/src/lando/api/legacy/api/stacks.py +++ b/src/lando/api/legacy/api/stacks.py @@ -119,9 +119,7 @@ def get(phab: PhabricatorClient, revision_id: str): revisions_response = [] for _phid, phab_revision in stack_data.revisions.items(): - lando_revision = Revision.query.filter( - Revision.revision_id == phab_revision["id"] - ).one_or_none() + lando_revision = Revision.one_or_none(revision_id=phab_revision["id"]) revision_phid = PhabricatorClient.expect(phab_revision, "phid") fields = PhabricatorClient.expect(phab_revision, "fields") diff_phid = PhabricatorClient.expect(fields, "diffPHID") diff --git a/src/lando/api/legacy/api/transplants.py b/src/lando/api/legacy/api/transplants.py index edbebb8c..7e3620e4 100644 --- a/src/lando/api/legacy/api/transplants.py +++ b/src/lando/api/legacy/api/transplants.py @@ -55,7 +55,6 @@ get_landable_repos_for_revision_data, request_extended_revision_data, ) -from lando.api.legacy.storage import db from lando.api.legacy.tasks import admin_remove_phab_project from lando.api.legacy.transplants import ( TransplantAssessment, @@ -354,10 +353,8 @@ def post(phab: PhabricatorClient, data: dict): lando_revision = Revision.get_from_revision_id(revision_id) if not lando_revision: lando_revision = Revision(revision_id=revision_id) - db.session.add(lando_revision) - lando_revision.diff_id = diff_id - db.session.commit() + lando_revision.save() revision_reviewers[lando_revision.id] = get_approved_by_ids( phab, @@ -373,7 +370,7 @@ def post(phab: PhabricatorClient, data: dict): raw_diff = phab.call_conduit("differential.getrawdiff", diffID=diff["id"]) lando_revision.set_patch(raw_diff, patch_data) - db.session.commit() + lando_revision.save() lando_revisions.append(lando_revision) ldap_username = g.auth0_user.email @@ -384,8 +381,7 @@ def post(phab: PhabricatorClient, data: dict): ) ) stack_ids = [revision.revision_id for revision in lando_revisions] - with db.session.begin_nested(): - LandingJob.lock_table() + with LandingJob.lock_table(): if ( LandingJob.revisions_query(stack_ids) .filter( @@ -412,7 +408,7 @@ def post(phab: PhabricatorClient, data: dict): # Submit landing job. job.status = LandingJobStatus.SUBMITTED job.set_landed_revision_diffs() - db.session.commit() + job.save() logger.info(f"New landing job {job.id} created for {landing_repo.tree} repo.") diff --git a/src/lando/api/legacy/app.py b/src/lando/api/legacy/app.py index fc46084b..d3f5a30f 100644 --- a/src/lando/api/legacy/app.py +++ b/src/lando/api/legacy/app.py @@ -20,7 +20,6 @@ from lando.api.legacy.repos import repo_clone_subsystem from lando.api.legacy.sentry import sentry_subsystem from lando.api.legacy.smtp import smtp_subsystem -from lando.api.legacy.storage import db_subsystem from lando.api.legacy.systems import Subsystem from lando.api.legacy.treestatus import treestatus_subsystem from lando.api.legacy.ui import lando_ui_subsystem @@ -36,7 +35,6 @@ auth0_subsystem, cache_subsystem, celery_subsystem, - db_subsystem, lando_ui_subsystem, phabricator_subsystem, smtp_subsystem, @@ -54,8 +52,6 @@ def load_config() -> dict[str, Any]: "MAIL_SUPPRESS_SEND": bool(os.getenv("MAIL_SUPPRESS_SEND")), "MAIL_USE_SSL": bool(os.getenv("MAIL_USE_SSL")), "MAIL_USE_TLS": bool(os.getenv("MAIL_USE_TLS")), - "SQLALCHEMY_DATABASE_URI": os.getenv("DATABASE_URL"), - "SQLALCHEMY_TRACK_MODIFICATIONS": False, "VERSION": version(), } diff --git a/src/lando/api/legacy/cli.py b/src/lando/api/legacy/cli.py index d74e538a..2064d6f1 100644 --- a/src/lando/api/legacy/cli.py +++ b/src/lando/api/legacy/cli.py @@ -82,9 +82,6 @@ def landing_worker(): @cli.command(name="run-pre-deploy-sequence") def run_pre_deploy_sequence(): """Runs the sequence of commands required before a deployment.""" - from lando.api.legacy.storage import db_subsystem - - db_subsystem.ensure_ready() ConfigurationVariable.set( ConfigurationKey.API_IN_MAINTENANCE, VariableType.BOOL, "1" ) @@ -96,9 +93,6 @@ def run_pre_deploy_sequence(): @cli.command(name="run-post-deploy-sequence") def run_post_deploy_sequence(): """Runs the sequence of commands required after a deployment.""" - from lando.api.legacy.storage import db_subsystem - - db_subsystem.ensure_ready() ConfigurationVariable.set( ConfigurationKey.API_IN_MAINTENANCE, VariableType.BOOL, "0" ) diff --git a/src/lando/api/legacy/storage.py b/src/lando/api/legacy/storage.py deleted file mode 100644 index ae6afcef..00000000 --- a/src/lando/api/legacy/storage.py +++ /dev/null @@ -1,35 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -from flask_migrate import Migrate -from flask_sqlalchemy import SQLAlchemy -from sqlalchemy.exc import DBAPIError, SQLAlchemyError - -from lando.api.legacy.systems import Subsystem - -db = SQLAlchemy() -migrate = Migrate() - - -class DBSubsystem(Subsystem): - name = "database" - - def init_app(self, app): - super().init_app(app) - db.init_app(app) - migrate.init_app(app=app, db=db) - - def healthy(self): - try: - with db.engine.connect() as conn: - conn.execute("SELECT 1;") - except DBAPIError as exc: - return "DBAPIError: {!s}".format(exc) - except SQLAlchemyError as exc: - return "SQLAlchemyError: {!s}".format(exc) - - return True - - -db_subsystem = DBSubsystem() diff --git a/src/lando/api/legacy/transplants.py b/src/lando/api/legacy/transplants.py index 6674d071..5dd740f3 100644 --- a/src/lando/api/legacy/transplants.py +++ b/src/lando/api/legacy/transplants.py @@ -303,10 +303,10 @@ def warning_revision_missing_testing_tag( @RevisionWarningCheck(6, "Revision has a diff warning.", True) def warning_diff_warning(*, revision, diff, **kwargs): - warnings = DiffWarning.query.filter( - DiffWarning.revision_id == revision["id"], - DiffWarning.diff_id == diff["id"], - DiffWarning.status == DiffWarningStatus.ACTIVE, + warnings = DiffWarning.objects.filter( + revision_id=revision["id"], + diff_id=diff["id"], + status=DiffWarningStatus.ACTIVE, ) if warnings.count(): return [w.data for w in warnings] diff --git a/src/lando/api/legacy/workers/landing_worker.py b/src/lando/api/legacy/workers/landing_worker.py index 032d7f9f..cbded17a 100644 --- a/src/lando/api/legacy/workers/landing_worker.py +++ b/src/lando/api/legacy/workers/landing_worker.py @@ -26,8 +26,8 @@ TreeApprovalRequired, TreeClosed, ) -from lando.api.legacy.models.configuration import ConfigurationKey -from lando.api.legacy.models.landing_job import LandingJob, LandingJobAction, LandingJobStatus +from lando.main.models.configuration import ConfigurationKey +from lando.main.models.landing_job import LandingJob, LandingJobAction, LandingJobStatus from lando.api.legacy.notifications import ( notify_user_of_bug_update_failure, notify_user_of_landing_failure, @@ -36,7 +36,6 @@ Repo, repo_clone_subsystem, ) -from lando.api.legacy.storage import SQLAlchemy, db from lando.api.legacy.tasks import phab_trigger_repo_update from lando.api.legacy.treestatus import ( TreeStatus, @@ -51,7 +50,7 @@ @contextmanager -def job_processing(worker: LandingWorker, job: LandingJob, db: SQLAlchemy): +def job_processing(worker: LandingWorker, job: LandingJob): """Mutex-like context manager that manages job processing miscellany. This context manager facilitates graceful worker shutdown, tracks the duration of @@ -60,14 +59,13 @@ def job_processing(worker: LandingWorker, job: LandingJob, db: SQLAlchemy): Args: worker: the landing worker that is processing jobs job: the job currently being processed - db: active database session """ start_time = datetime.now() try: yield finally: job.duration_seconds = (datetime.now() - start_time).seconds - db.session.commit() + job.save() class LandingWorker(Worker): diff --git a/src/lando/api/tests/conftest.py b/src/lando/api/tests/conftest.py index 25892165..98fab788 100644 --- a/src/lando/api/tests/conftest.py +++ b/src/lando/api/tests/conftest.py @@ -14,7 +14,6 @@ import redis import requests import requests_mock -import sqlalchemy from flask import current_app from pytest_flask.plugin import JSONResponse @@ -259,22 +258,6 @@ def app(versionfile, docker_env_vars, disable_migrations, mocked_repo_config): return flask_app -@pytest.fixture -def db(app): - """Reset database for each test.""" - try: - _db.engine.connect() - except sqlalchemy.exc.OperationalError: - if EXTERNAL_SERVICES_SHOULD_BE_PRESENT: - raise - else: - pytest.skip("Could not connect to PostgreSQL") - _db.create_all() - yield _db - _db.session.remove() - _db.drop_all() - - @pytest.fixture def jwks(monkeypatch): monkeypatch.setattr("landoapi.auth.get_jwks", lambda *args, **kwargs: TEST_JWKS) diff --git a/src/lando/api/tests/test_diff_warnings.py b/src/lando/api/tests/test_diff_warnings.py index 17c298bb..5b9b7201 100644 --- a/src/lando/api/tests/test_diff_warnings.py +++ b/src/lando/api/tests/test_diff_warnings.py @@ -4,7 +4,7 @@ import pytest -from lando.api.legacy.models.revisions import ( +from lando.main.models.revision import ( DiffWarning, DiffWarningGroup, DiffWarningStatus, @@ -57,7 +57,7 @@ def test_diff_warning_create(db, client, diff_warning_data, phab_header): assert "id" in response.json pk = response.json["id"] - warning = DiffWarning.query.get(pk) + warning = DiffWarning.objects.get(pk=pk) assert warning.group == DiffWarningGroup.LINT assert warning.revision_id == 1 assert warning.diff_id == 1 @@ -79,7 +79,7 @@ def test_diff_warning_delete(db, client, diff_warning_data, phab_header): ) assert response.status_code == 201 pk = response.json["id"] - warning = DiffWarning.query.get(pk) + warning = DiffWarning.objects.get(pk=pk) assert warning.status == DiffWarningStatus.ACTIVE response = client.delete( @@ -89,7 +89,7 @@ def test_diff_warning_delete(db, client, diff_warning_data, phab_header): assert response.status_code == 200 - warning = DiffWarning.query.get(pk) + warning = DiffWarning.objects.get(pk=pk) assert warning.status == DiffWarningStatus.ARCHIVED diff --git a/src/lando/api/tests/test_health.py b/src/lando/api/tests/test_health.py index 5da055ca..29c2e554 100644 --- a/src/lando/api/tests/test_health.py +++ b/src/lando/api/tests/test_health.py @@ -5,24 +5,10 @@ from unittest.mock import Mock import redis -from sqlalchemy.exc import SQLAlchemyError from lando.api.legacy.auth import auth0_subsystem from lando.api.legacy.cache import cache_subsystem from lando.api.legacy.phabricator import PhabricatorAPIException, phabricator_subsystem -from lando.api.legacy.storage import db_subsystem - - -def test_database_healthy(db): - assert db_subsystem.healthy() is True - - -def test_database_unhealthy(db, monkeypatch): - mock_db = Mock(db) - monkeypatch.setattr("landoapi.storage.db", mock_db) - - mock_db.engine.connect.side_effect = SQLAlchemyError - assert db_subsystem.healthy() is not True def test_phabricator_healthy(app, phabdouble): diff --git a/src/lando/api/tests/test_landing_job.py b/src/lando/api/tests/test_landing_job.py index 61cb55ce..90d59681 100644 --- a/src/lando/api/tests/test_landing_job.py +++ b/src/lando/api/tests/test_landing_job.py @@ -4,7 +4,7 @@ import pytest -from lando.api.legacy.models.landing_job import LandingJob, LandingJobStatus +from lando.main.models.landing_job import LandingJob, LandingJobStatus @pytest.fixture diff --git a/src/lando/api/tests/test_landings.py b/src/lando/api/tests/test_landings.py index 723ba376..b52a3362 100644 --- a/src/lando/api/tests/test_landings.py +++ b/src/lando/api/tests/test_landings.py @@ -9,12 +9,12 @@ import pytest from lando.api.legacy.hg import AUTOFORMAT_COMMIT_MESSAGE, HgRepo -from lando.api.legacy.models.landing_job import ( +from lando.main.models.landing_job import ( LandingJob, LandingJobStatus, add_job_with_revisions, ) -from lando.api.legacy.models.revisions import Revision +from lando.main.models.revision import Revision from lando.api.legacy.repos import SCM_LEVEL_3, Repo from lando.api.legacy.workers.landing_worker import LandingWorker @@ -878,5 +878,5 @@ def test_landing_job_revisions_sorting( new_ordering = [revisions[2], revisions[0], revisions[1]] job.sort_revisions(new_ordering) db.session.commit() - job = LandingJob.query.get(job.id) + job = LandingJob.objects.get(id=job.id) assert job.revisions == new_ordering diff --git a/src/lando/api/tests/test_models.py b/src/lando/api/tests/test_models.py deleted file mode 100644 index 226217db..00000000 --- a/src/lando/api/tests/test_models.py +++ /dev/null @@ -1,33 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -from lando.api.legacy.models.base import Base - - -class TestModelsBase: - """Tests various attributes on the `Base` model.""" - - def test___tablename__(self): - """Checks various capitalization combinations get parsed correctly.""" - - class SomeModel(Base): - pass - - class ALLCAPSModel(Base): - pass - - class Model(Base): - pass - - assert SomeModel.__tablename__ == "some_model" - assert Model.__tablename__ == "model" - assert ALLCAPSModel.__tablename__ == "allcaps_model" - - def test___repr__(self): - """Checks the default printable representation of the Base model.""" - - class AnotherModel(Base): - pass - - test = AnotherModel(id=1) - assert repr(test) == "" diff --git a/src/lando/api/tests/test_notifications.py b/src/lando/api/tests/test_notifications.py index 937de0a5..79881663 100644 --- a/src/lando/api/tests/test_notifications.py +++ b/src/lando/api/tests/test_notifications.py @@ -7,8 +7,8 @@ from lando.api.legacy.celery import FlaskCelery from lando.api.legacy.email import make_failure_email -from lando.api.legacy.models.landing_job import LandingJob -from lando.api.legacy.models.revisions import Revision +from lando.main.models.landing_job import LandingJob +from lando.main.models.revision import Revision from lando.api.legacy.notifications import notify_user_of_landing_failure from lando.api.legacy.tasks import send_landing_failure_email diff --git a/src/lando/api/tests/test_transplants.py b/src/lando/api/tests/test_transplants.py index bd1f2821..8adbf8b8 100644 --- a/src/lando/api/tests/test_transplants.py +++ b/src/lando/api/tests/test_transplants.py @@ -8,13 +8,12 @@ from lando.api.legacy.hg import HgRepo from lando.api.legacy.mocks.canned_responses.auth0 import CANNED_USERINFO -from lando.api.legacy.models.landing_job import ( +from lando.main.models.landing_job import ( LandingJob, LandingJobStatus, add_job_with_revisions, ) -from lando.api.legacy.models.revisions import Revision -from lando.api.legacy.models.transplant import Transplant +from lando.main.models.revision import Revision from lando.api.legacy.phabricator import PhabricatorRevisionStatus, ReviewerStatus from lando.api.legacy.repos import DONTBUILD, SCM_CONDUIT, SCM_LEVEL_3, Repo from lando.api.legacy.reviews import get_collated_reviewers @@ -49,9 +48,7 @@ def _create_landing_job( } revisions = [] for revision_id, diff_id in landing_path: - revision = Revision.query.filter( - Revision.revision_id == revision_id - ).one_or_none() + revision = Revision.one_or_none(revision_id=revision_id) if not revision: revision = Revision(revision_id=revision_id) revision.diff_id = diff_id @@ -83,9 +80,7 @@ def _create_landing_job_with_no_linked_revisions( db.session.add(job) revisions = [] for revision_id, diff_id in landing_path: - revision = Revision.query.filter( - Revision.revision_id == revision_id - ).one_or_none() + revision = Revision.one_or_none(revision_id=revision_id) if not revision: revision = Revision(revision_id=revision_id) revision.diff_id = diff_id @@ -705,7 +700,7 @@ def test_integrated_transplant_simple_stack_saves_data_in_db( db.session.close() # Get LandingJob object by its id - job = LandingJob.query.get(job_id) + job = LandingJob.objects.get(pk=job_id) assert job.id == job_id assert [(revision.revision_id, revision.diff_id) for revision in job.revisions] == [ (r1["id"], d1["id"]), @@ -785,7 +780,7 @@ def test_integrated_transplant_records_approvers_peers_and_owners( db.session.close() # Get LandingJob object by its id - job = LandingJob.query.get(job_id) + job = LandingJob.objects.get(pk=job_id) assert job.id == job_id assert [(revision.revision_id, revision.diff_id) for revision in job.revisions] == [ (r1["id"], d1["id"]), @@ -845,7 +840,7 @@ def test_integrated_transplant_updated_diff_id_reflected_in_landed_revisions( db.session.close() # Get LandingJob object by its id. - job = LandingJob.query.get(job_1_id) + job = LandingJob.objects.get(pk=job_1_id) assert job.id == job_1_id assert [(revision.revision_id, revision.diff_id) for revision in job.revisions] == [ (r1["id"], d1a["id"]), @@ -860,7 +855,7 @@ def test_integrated_transplant_updated_diff_id_reflected_in_landed_revisions( headers=auth0_mock.mock_headers, ) - job = LandingJob.query.get(job_1_id) + job = LandingJob.objects.get(pk=job_1_id) assert job.status == LandingJobStatus.CANCELLED d1b = phabdouble.diff(revision=r1) @@ -881,8 +876,8 @@ def test_integrated_transplant_updated_diff_id_reflected_in_landed_revisions( db.session.close() # Get LandingJob objects by their ids. - job_1 = LandingJob.query.get(job_1_id) - job_2 = LandingJob.query.get(job_2_id) + job_1 = LandingJob.objects.get(pk=job_1_id) + job_2 = LandingJob.objects.get(pk=job_2_id) # The Revision objects always track the latest revisions. assert [ @@ -1205,10 +1200,6 @@ def test_warning_wip_commit_message(phabdouble): assert warning_wip_commit_message(revision=revision) is not None -def test_display_branch_head(): - assert Transplant(revision_order=["1", "2"]).head_revision == "D2" - - def test_codefreeze_datetime_mock(codefreeze_datetime): dt = codefreeze_datetime() assert dt.now(tz=timezone.utc) == datetime(2000, 1, 5, 0, 0, 0, tzinfo=timezone.utc) diff --git a/src/lando/api/tests/test_try.py b/src/lando/api/tests/test_try.py index 1a4dbdaf..c4d5a418 100644 --- a/src/lando/api/tests/test_try.py +++ b/src/lando/api/tests/test_try.py @@ -11,7 +11,7 @@ get_timestamp_from_git_date_header, parse_git_author_information, ) -from lando.api.legacy.models.landing_job import LandingJob, LandingJobStatus +from lando.main.models.landing_job import LandingJob, LandingJobStatus from lando.api.legacy.repos import SCM_LEVEL_1, Repo from lando.api.legacy.workers.landing_worker import LandingWorker diff --git a/src/lando/main/models/base.py b/src/lando/main/models/base.py index 9afc8615..0c5160e6 100644 --- a/src/lando/main/models/base.py +++ b/src/lando/main/models/base.py @@ -1,5 +1,6 @@ from __future__ import annotations +from contextlib import ContextDecorator import logging import os import subprocess @@ -7,6 +8,7 @@ from pathlib import Path from django.db import models +from django.db import connection from lando import settings from lando.utils import GitPatchHelper @@ -23,6 +25,30 @@ class BaseModel(models.Model): class Meta: abstract = True + class lock_table(ContextDecorator): + """Decorator to lock table for current model.""" + + def __init__(self, model, lock): + self.lock = lock + + if lock not in ("SHARE ROW EXCLUSIVE", ): + raise ValueError(f"{lock} not valid.") + + def __enter__(self): + cursor = connection.cursor() + cursor.execute(f"LOCK TABLE {self._meta.db_table} IN {self.lock} MODE") + + def __exit__(self, exc_type, exc_value, traceback): + pass + + @classmethod + def one_or_none(cls, *args, **kwargs): + try: + result = cls.objects.get(*args, **kwargs) + except cls.DoesNotExist: + return None + return result + class Repo(BaseModel): name = models.CharField(max_length=255, unique=True) diff --git a/src/lando/main/models/landing_job.py b/src/lando/main/models/landing_job.py index 677d3cd7..eb74a05e 100644 --- a/src/lando/main/models/landing_job.py +++ b/src/lando/main/models/landing_job.py @@ -180,7 +180,7 @@ def revisions_query(cls, revisions: Iterable[str]) -> QuerySet: not be included in this query. """ revisions = [str(int(r)) for r in revisions] - return cls.query.filter(revision_id__in=revisions) + return cls.objects.filter(revision_id__in=revisions) @classmethod def job_queue_query(