Skip to content

Commit a01ae86

Browse files
authored
models: add table lock and translate old db usage (bug 1886854) (#45)
- add table lock functionality - translate old db queries and ORM usage - fix few incorrect imports - add one_or_none method to base model - remove unneeded tests - remove db fixture
1 parent 81d2e51 commit a01ae86

20 files changed

+71
-173
lines changed

src/lando/api/legacy/api/diff_warnings.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
from lando.api.legacy.decorators import require_phabricator_api_key
1717
from lando.main.models.revision import DiffWarning, DiffWarningStatus
18-
from lando.api.legacy.storage import db
1918

2019
logger = logging.getLogger(__name__)
2120

@@ -41,15 +40,14 @@ def post(data: dict):
4140
type="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400",
4241
)
4342
warning = DiffWarning(**data)
44-
db.session.add(warning)
45-
db.session.commit()
43+
warning.save()
4644
return warning.serialize(), 201
4745

4846

4947
@require_phabricator_api_key(provide_client=False)
5048
def delete(pk: str):
5149
"""Archive a `DiffWarning` based on provided pk."""
52-
warning = DiffWarning.query.get(pk)
50+
warning = DiffWarning.objects.get(pk=pk)
5351
if not warning:
5452
return problem(
5553
400,
@@ -58,17 +56,17 @@ def delete(pk: str):
5856
type="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400",
5957
)
6058
warning.status = DiffWarningStatus.ARCHIVED
61-
db.session.commit()
59+
warning.save()
6260
return warning.serialize(), 200
6361

6462

6563
@require_phabricator_api_key(provide_client=False)
6664
def get(revision_id: str, diff_id: str, group: str):
6765
"""Return a list of active revision diff warnings, if any."""
68-
warnings = DiffWarning.query.filter(
69-
DiffWarning.revision_id == revision_id,
70-
DiffWarning.diff_id == diff_id,
71-
DiffWarning.status == DiffWarningStatus.ACTIVE,
72-
DiffWarning.group == group,
66+
warnings = DiffWarning.objects.filter(
67+
revision_id=revision_id,
68+
diff_id=diff_id,
69+
status=DiffWarningStatus.ACTIVE,
70+
group=group,
7371
)
7472
return [w.serialize() for w in warnings], 200

src/lando/api/legacy/api/landing_jobs.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
from lando.api import auth
1010
from lando.main.models.landing_job import LandingJob, LandingJobAction, LandingJobStatus
11-
from lando.api.legacy.storage import db
1211

1312
logger = logging.getLogger(__name__)
1413

@@ -32,6 +31,7 @@ def put(landing_job_id: str, data: dict):
3231
updated (for example, when trying to cancel a job that is already in
3332
progress).
3433
"""
34+
# TODO: fix this based on locks/etc.
3535
landing_job = LandingJob.query.with_for_update().get(landing_job_id)
3636

3737
if not landing_job:
@@ -61,7 +61,7 @@ def put(landing_job_id: str, data: dict):
6161

6262
if landing_job.status in (LandingJobStatus.SUBMITTED, LandingJobStatus.DEFERRED):
6363
landing_job.transition_status(LandingJobAction.CANCEL)
64-
db.session.commit()
64+
landing_job.save()
6565
return {"id": landing_job.id}, 200
6666
else:
6767
raise ProblemException(

src/lando/api/legacy/api/stacks.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,7 @@ def get(phab: PhabricatorClient, revision_id: str):
119119

120120
revisions_response = []
121121
for _phid, phab_revision in stack_data.revisions.items():
122-
lando_revision = Revision.query.filter(
123-
Revision.revision_id == phab_revision["id"]
124-
).one_or_none()
122+
lando_revision = Revision.one_or_none(revision_id=phab_revision["id"])
125123
revision_phid = PhabricatorClient.expect(phab_revision, "phid")
126124
fields = PhabricatorClient.expect(phab_revision, "fields")
127125
diff_phid = PhabricatorClient.expect(fields, "diffPHID")

src/lando/api/legacy/api/transplants.py

+4-8
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@
5555
get_landable_repos_for_revision_data,
5656
request_extended_revision_data,
5757
)
58-
from lando.api.legacy.storage import db
5958
from lando.api.legacy.tasks import admin_remove_phab_project
6059
from lando.api.legacy.transplants import (
6160
TransplantAssessment,
@@ -354,10 +353,8 @@ def post(phab: PhabricatorClient, data: dict):
354353
lando_revision = Revision.get_from_revision_id(revision_id)
355354
if not lando_revision:
356355
lando_revision = Revision(revision_id=revision_id)
357-
db.session.add(lando_revision)
358-
359356
lando_revision.diff_id = diff_id
360-
db.session.commit()
357+
lando_revision.save()
361358

362359
revision_reviewers[lando_revision.id] = get_approved_by_ids(
363360
phab,
@@ -373,7 +370,7 @@ def post(phab: PhabricatorClient, data: dict):
373370

374371
raw_diff = phab.call_conduit("differential.getrawdiff", diffID=diff["id"])
375372
lando_revision.set_patch(raw_diff, patch_data)
376-
db.session.commit()
373+
lando_revision.save()
377374
lando_revisions.append(lando_revision)
378375

379376
ldap_username = g.auth0_user.email
@@ -384,8 +381,7 @@ def post(phab: PhabricatorClient, data: dict):
384381
)
385382
)
386383
stack_ids = [revision.revision_id for revision in lando_revisions]
387-
with db.session.begin_nested():
388-
LandingJob.lock_table()
384+
with LandingJob.lock_table():
389385
if (
390386
LandingJob.revisions_query(stack_ids)
391387
.filter(
@@ -412,7 +408,7 @@ def post(phab: PhabricatorClient, data: dict):
412408
# Submit landing job.
413409
job.status = LandingJobStatus.SUBMITTED
414410
job.set_landed_revision_diffs()
415-
db.session.commit()
411+
job.save()
416412

417413
logger.info(f"New landing job {job.id} created for {landing_repo.tree} repo.")
418414

src/lando/api/legacy/app.py

-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
from lando.api.legacy.repos import repo_clone_subsystem
2121
from lando.api.legacy.sentry import sentry_subsystem
2222
from lando.api.legacy.smtp import smtp_subsystem
23-
from lando.api.legacy.storage import db_subsystem
2423
from lando.api.legacy.systems import Subsystem
2524
from lando.api.legacy.treestatus import treestatus_subsystem
2625
from lando.api.legacy.ui import lando_ui_subsystem
@@ -36,7 +35,6 @@
3635
auth0_subsystem,
3736
cache_subsystem,
3837
celery_subsystem,
39-
db_subsystem,
4038
lando_ui_subsystem,
4139
phabricator_subsystem,
4240
smtp_subsystem,
@@ -54,8 +52,6 @@ def load_config() -> dict[str, Any]:
5452
"MAIL_SUPPRESS_SEND": bool(os.getenv("MAIL_SUPPRESS_SEND")),
5553
"MAIL_USE_SSL": bool(os.getenv("MAIL_USE_SSL")),
5654
"MAIL_USE_TLS": bool(os.getenv("MAIL_USE_TLS")),
57-
"SQLALCHEMY_DATABASE_URI": os.getenv("DATABASE_URL"),
58-
"SQLALCHEMY_TRACK_MODIFICATIONS": False,
5955
"VERSION": version(),
6056
}
6157

src/lando/api/legacy/cli.py

-6
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,6 @@ def landing_worker():
8282
@cli.command(name="run-pre-deploy-sequence")
8383
def run_pre_deploy_sequence():
8484
"""Runs the sequence of commands required before a deployment."""
85-
from lando.api.legacy.storage import db_subsystem
86-
87-
db_subsystem.ensure_ready()
8885
ConfigurationVariable.set(
8986
ConfigurationKey.API_IN_MAINTENANCE, VariableType.BOOL, "1"
9087
)
@@ -96,9 +93,6 @@ def run_pre_deploy_sequence():
9693
@cli.command(name="run-post-deploy-sequence")
9794
def run_post_deploy_sequence():
9895
"""Runs the sequence of commands required after a deployment."""
99-
from lando.api.legacy.storage import db_subsystem
100-
101-
db_subsystem.ensure_ready()
10296
ConfigurationVariable.set(
10397
ConfigurationKey.API_IN_MAINTENANCE, VariableType.BOOL, "0"
10498
)

src/lando/api/legacy/storage.py

-35
This file was deleted.

src/lando/api/legacy/transplants.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,10 @@ def warning_revision_missing_testing_tag(
303303

304304
@RevisionWarningCheck(6, "Revision has a diff warning.", True)
305305
def warning_diff_warning(*, revision, diff, **kwargs):
306-
warnings = DiffWarning.query.filter(
307-
DiffWarning.revision_id == revision["id"],
308-
DiffWarning.diff_id == diff["id"],
309-
DiffWarning.status == DiffWarningStatus.ACTIVE,
306+
warnings = DiffWarning.objects.filter(
307+
revision_id=revision["id"],
308+
diff_id=diff["id"],
309+
status=DiffWarningStatus.ACTIVE,
310310
)
311311
if warnings.count():
312312
return [w.data for w in warnings]

src/lando/api/legacy/workers/landing_worker.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
TreeApprovalRequired,
2727
TreeClosed,
2828
)
29-
from lando.api.legacy.models.configuration import ConfigurationKey
30-
from lando.api.legacy.models.landing_job import LandingJob, LandingJobAction, LandingJobStatus
29+
from lando.main.models.configuration import ConfigurationKey
30+
from lando.main.models.landing_job import LandingJob, LandingJobAction, LandingJobStatus
3131
from lando.api.legacy.notifications import (
3232
notify_user_of_bug_update_failure,
3333
notify_user_of_landing_failure,
@@ -36,7 +36,6 @@
3636
Repo,
3737
repo_clone_subsystem,
3838
)
39-
from lando.api.legacy.storage import SQLAlchemy, db
4039
from lando.api.legacy.tasks import phab_trigger_repo_update
4140
from lando.api.legacy.treestatus import (
4241
TreeStatus,
@@ -51,7 +50,7 @@
5150

5251

5352
@contextmanager
54-
def job_processing(worker: LandingWorker, job: LandingJob, db: SQLAlchemy):
53+
def job_processing(worker: LandingWorker, job: LandingJob):
5554
"""Mutex-like context manager that manages job processing miscellany.
5655
5756
This context manager facilitates graceful worker shutdown, tracks the duration of
@@ -60,14 +59,13 @@ def job_processing(worker: LandingWorker, job: LandingJob, db: SQLAlchemy):
6059
Args:
6160
worker: the landing worker that is processing jobs
6261
job: the job currently being processed
63-
db: active database session
6462
"""
6563
start_time = datetime.now()
6664
try:
6765
yield
6866
finally:
6967
job.duration_seconds = (datetime.now() - start_time).seconds
70-
db.session.commit()
68+
job.save()
7169

7270

7371
class LandingWorker(Worker):

src/lando/api/tests/conftest.py

-17
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import redis
1515
import requests
1616
import requests_mock
17-
import sqlalchemy
1817
from flask import current_app
1918
from pytest_flask.plugin import JSONResponse
2019

@@ -259,22 +258,6 @@ def app(versionfile, docker_env_vars, disable_migrations, mocked_repo_config):
259258
return flask_app
260259

261260

262-
@pytest.fixture
263-
def db(app):
264-
"""Reset database for each test."""
265-
try:
266-
_db.engine.connect()
267-
except sqlalchemy.exc.OperationalError:
268-
if EXTERNAL_SERVICES_SHOULD_BE_PRESENT:
269-
raise
270-
else:
271-
pytest.skip("Could not connect to PostgreSQL")
272-
_db.create_all()
273-
yield _db
274-
_db.session.remove()
275-
_db.drop_all()
276-
277-
278261
@pytest.fixture
279262
def jwks(monkeypatch):
280263
monkeypatch.setattr("landoapi.auth.get_jwks", lambda *args, **kwargs: TEST_JWKS)

src/lando/api/tests/test_diff_warnings.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import pytest
66

7-
from lando.api.legacy.models.revisions import (
7+
from lando.main.models.revision import (
88
DiffWarning,
99
DiffWarningGroup,
1010
DiffWarningStatus,
@@ -57,7 +57,7 @@ def test_diff_warning_create(db, client, diff_warning_data, phab_header):
5757
assert "id" in response.json
5858

5959
pk = response.json["id"]
60-
warning = DiffWarning.query.get(pk)
60+
warning = DiffWarning.objects.get(pk=pk)
6161
assert warning.group == DiffWarningGroup.LINT
6262
assert warning.revision_id == 1
6363
assert warning.diff_id == 1
@@ -79,7 +79,7 @@ def test_diff_warning_delete(db, client, diff_warning_data, phab_header):
7979
)
8080
assert response.status_code == 201
8181
pk = response.json["id"]
82-
warning = DiffWarning.query.get(pk)
82+
warning = DiffWarning.objects.get(pk=pk)
8383
assert warning.status == DiffWarningStatus.ACTIVE
8484

8585
response = client.delete(
@@ -89,7 +89,7 @@ def test_diff_warning_delete(db, client, diff_warning_data, phab_header):
8989

9090
assert response.status_code == 200
9191

92-
warning = DiffWarning.query.get(pk)
92+
warning = DiffWarning.objects.get(pk=pk)
9393
assert warning.status == DiffWarningStatus.ARCHIVED
9494

9595

src/lando/api/tests/test_health.py

-14
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,10 @@
55
from unittest.mock import Mock
66

77
import redis
8-
from sqlalchemy.exc import SQLAlchemyError
98

109
from lando.api.legacy.auth import auth0_subsystem
1110
from lando.api.legacy.cache import cache_subsystem
1211
from lando.api.legacy.phabricator import PhabricatorAPIException, phabricator_subsystem
13-
from lando.api.legacy.storage import db_subsystem
14-
15-
16-
def test_database_healthy(db):
17-
assert db_subsystem.healthy() is True
18-
19-
20-
def test_database_unhealthy(db, monkeypatch):
21-
mock_db = Mock(db)
22-
monkeypatch.setattr("landoapi.storage.db", mock_db)
23-
24-
mock_db.engine.connect.side_effect = SQLAlchemyError
25-
assert db_subsystem.healthy() is not True
2612

2713

2814
def test_phabricator_healthy(app, phabdouble):

src/lando/api/tests/test_landing_job.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import pytest
66

7-
from lando.api.legacy.models.landing_job import LandingJob, LandingJobStatus
7+
from lando.main.models.landing_job import LandingJob, LandingJobStatus
88

99

1010
@pytest.fixture

src/lando/api/tests/test_landings.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
import pytest
1010

1111
from lando.api.legacy.hg import AUTOFORMAT_COMMIT_MESSAGE, HgRepo
12-
from lando.api.legacy.models.landing_job import (
12+
from lando.main.models.landing_job import (
1313
LandingJob,
1414
LandingJobStatus,
1515
add_job_with_revisions,
1616
)
17-
from lando.api.legacy.models.revisions import Revision
17+
from lando.main.models.revision import Revision
1818
from lando.api.legacy.repos import SCM_LEVEL_3, Repo
1919
from lando.api.legacy.workers.landing_worker import LandingWorker
2020

@@ -878,5 +878,5 @@ def test_landing_job_revisions_sorting(
878878
new_ordering = [revisions[2], revisions[0], revisions[1]]
879879
job.sort_revisions(new_ordering)
880880
db.session.commit()
881-
job = LandingJob.query.get(job.id)
881+
job = LandingJob.objects.get(id=job.id)
882882
assert job.revisions == new_ordering

0 commit comments

Comments
 (0)