Merge ~r00ta/maas:MAASENG-2764 into maas:master

Proposed by Jacopo Rota
Status: Merged
Approved by: Jacopo Rota
Approved revision: 720d802632f5cc06960f89fe07e909884efec439
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~r00ta/maas:MAASENG-2764
Merge into: maas:master
Diff against target: 84 lines (+44/-3)
2 files modified
src/maasapiserver/common/db/__init__.py (+3/-1)
src/tests/maasapiserver/common/api/test_db.py (+41/-2)
Reviewer Review Type Date Requested Status
MAAS Lander Approve
Björn Tillenius Approve
Review via email: mp+461137@code.launchpad.net

Commit message

feat: set transaction isolation level to REPEATABLE READ in maasapiserver

Description of the change

The transaction level for the django sessions is set to REPEATABLE READ. This MP aims to implement the same strategy for maasapiserver.

Jira link: https://warthogs.atlassian.net/browse/MAASENG-2764

To post a comment you must log in.
~r00ta/maas:MAASENG-2764 updated
720d802... by Jacopo Rota

MAASENG-2764: set transaction isolation level to REPEATABLE READ in maasapiserver

Revision history for this message
Björn Tillenius (bjornt) wrote :

+1

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b MAASENG-2764 lp:~r00ta/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: SUCCESS
COMMIT: 720d802632f5cc06960f89fe07e909884efec439

review: Approve

Update scan failed

At least one of the branches involved have failed to scan. You can manually schedule a rescan if required.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasapiserver/common/db/__init__.py b/src/maasapiserver/common/db/__init__.py
2index 128ae7e..b3ca6c2 100644
3--- a/src/maasapiserver/common/db/__init__.py
4+++ b/src/maasapiserver/common/db/__init__.py
5@@ -6,4 +6,6 @@ from maasapiserver.settings import DatabaseConfig
6 class Database:
7 def __init__(self, config: DatabaseConfig, echo: bool = False):
8 self.config = config
9- self.engine = create_async_engine(config.dsn, echo=echo)
10+ self.engine = create_async_engine(
11+ config.dsn, echo=echo, isolation_level="REPEATABLE READ"
12+ )
13diff --git a/src/tests/maasapiserver/common/api/test_db.py b/src/tests/maasapiserver/common/api/test_db.py
14index 5499504..39bb43b 100644
15--- a/src/tests/maasapiserver/common/api/test_db.py
16+++ b/src/tests/maasapiserver/common/api/test_db.py
17@@ -3,7 +3,16 @@ from typing import AsyncIterator
18 from fastapi import Depends, FastAPI
19 from httpx import AsyncClient
20 import pytest
21-from sqlalchemy import Column, insert, Integer, MetaData, select, Table
22+from sqlalchemy import (
23+ Column,
24+ insert,
25+ Integer,
26+ MetaData,
27+ select,
28+ Table,
29+ Text,
30+ update,
31+)
32 from sqlalchemy.ext.asyncio import AsyncConnection
33
34 from maasapiserver.common.api.base import API, Handler, handler
35@@ -19,6 +28,7 @@ TestTable = Table(
36 "testing",
37 METADATA,
38 Column("id", Integer, primary_key=True),
39+ Column("name", Text),
40 )
41
42
43@@ -35,7 +45,7 @@ async def insert_app(
44 async def success(
45 self, conn: AsyncConnection = Depends(db_conn)
46 ) -> None:
47- await conn.execute(insert(TestTable).values(id=42))
48+ await conn.execute(insert(TestTable).values(id=42, name="default"))
49
50 @handler(path="/failure", methods=["GET"])
51 async def fail(self, conn: AsyncConnection = Depends(db_conn)) -> None:
52@@ -79,3 +89,32 @@ class TestDBSession:
53 async with db_connection.begin():
54 ids = await db_connection.scalars(select(TestTable.c.id))
55 assert list(ids) == []
56+
57+ async def test_isolation_level(
58+ self,
59+ insert_client: AsyncClient,
60+ db: Database,
61+ db_connection: AsyncConnection,
62+ ) -> None:
63+ response = await insert_client.get("/insert/success")
64+ assert response.status_code == 200
65+
66+ second_db_connection = await db.engine.connect()
67+
68+ async with db_connection.begin():
69+ async with second_db_connection.begin():
70+ assert (
71+ await db_connection.execute(
72+ select(TestTable.c.name).where(TestTable.c.id == 42)
73+ )
74+ ).first().name == "default"
75+ await second_db_connection.execute(
76+ update(TestTable)
77+ .where(TestTable.c.id == 42)
78+ .values(name="new value")
79+ )
80+ assert (
81+ await db_connection.execute(
82+ select(TestTable.c.name).where(TestTable.c.id == 42)
83+ )
84+ ).first().name == "default"

Subscribers

People subscribed via source and target branches