Skip to content

Commit 5a2cd63

Browse files
limit SQLAlchemy usage
1 parent 3af7060 commit 5a2cd63

File tree

11 files changed

+149
-84
lines changed

11 files changed

+149
-84
lines changed

autosubmit_api/builders/experiment_builder.py

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import datetime
2+
from autosubmit_api.logger import logger
23
from autosubmit_api.builders import BaseBuilder
34
from autosubmit_api.builders.configuration_facade_builder import (
45
AutosubmitConfigurationFacadeBuilder,
56
ConfigurationFacadeDirector,
67
)
7-
from autosubmit_api.database import tables
8-
from autosubmit_api.database.common import (
9-
create_autosubmit_db_engine,
10-
)
8+
from autosubmit_api.database.adapters import ExperimentDbAdapter, ExperimentDetailsDbAdapter
119
from autosubmit_api.database.models import ExperimentModel
1210

1311

@@ -23,32 +21,26 @@ def produce_base(self, expid):
2321
"""
2422
Produce basic information from the main experiment table
2523
"""
26-
with create_autosubmit_db_engine().connect() as conn:
27-
result = conn.execute(
28-
tables.experiment_table.select().where(
29-
tables.experiment_table.c.name == expid
30-
)
31-
).one()
24+
result = ExperimentDbAdapter().get_by_expid(expid)
3225

3326
# Set new product
3427
self._product = ExperimentModel(
35-
id=result.id,
36-
name=result.name,
37-
description=result.description,
38-
autosubmit_version=result.autosubmit_version,
28+
id=result["id"],
29+
name=result["name"],
30+
description=result["description"],
31+
autosubmit_version=result["autosubmit_version"],
3932
)
4033

4134
def produce_details(self):
4235
"""
4336
Produce data from the details table
4437
"""
4538
exp_id = self._product.id
46-
with create_autosubmit_db_engine().connect() as conn:
47-
result = conn.execute(
48-
tables.details_table.select().where(
49-
tables.details_table.c.exp_id == exp_id
50-
)
51-
).one_or_none()
39+
result = None
40+
try:
41+
result = ExperimentDetailsDbAdapter().get_by_exp_id(exp_id)
42+
except Exception:
43+
logger.error(f"Error getting details for exp_id {exp_id}")
5244

5345
# Set details props
5446
if result:
@@ -80,6 +72,7 @@ def produce_config_data(self):
8072
).isoformat()
8173
except Exception:
8274
self._product.modified = None
75+
logger.error(f"Error getting modified date for expid {expid}")
8376

8477
@property
8578
def product(self) -> ExperimentModel:

autosubmit_api/database/__init__.py

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,11 @@
1-
from sqlalchemy import Connection, Table
2-
from autosubmit_api.database.common import (
3-
create_as_times_db_engine,
4-
create_autosubmit_db_engine,
1+
from autosubmit_api.database.adapters import (
2+
ExperimentDbAdapter,
3+
ExperimentDetailsDbAdapter,
4+
ExperimentStatusDbAdapter,
55
)
6-
from autosubmit_api.database import tables
7-
8-
9-
def _create_autosubmit_db_tables(conn: Connection):
10-
experiment_table: Table = tables.ExperimentTable.__table__
11-
experiment_table.create(conn, checkfirst=True)
12-
details_table: Table = tables.DetailsTable.__table__
13-
details_table.create(conn, checkfirst=True)
14-
15-
16-
def _create_as_times_db_tables(conn: Connection):
17-
experiment_status_table: Table = tables.ExperimentStatusTable.__table__
18-
experiment_status_table.create(conn, checkfirst=True)
196

207

218
def prepare_db():
22-
with create_as_times_db_engine().connect() as conn:
23-
_create_as_times_db_tables(conn)
24-
conn.commit()
25-
26-
with create_autosubmit_db_engine().connect() as conn:
27-
_create_autosubmit_db_tables(conn)
28-
conn.commit()
9+
ExperimentDbAdapter().create_table()
10+
ExperimentDetailsDbAdapter().create_table()
11+
ExperimentStatusDbAdapter().create_table()

autosubmit_api/database/adapters/__init__.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,21 @@
1414
ExperimentStatusDbAdapter,
1515
)
1616
from autosubmit_api.database.adapters.graph_draw import ExpGraphDrawDBAdapter
17-
from autosubmit_api.database.adapters.join.experiment_join import ExperimentJoinDbAdapter
17+
from autosubmit_api.database.adapters.join.experiment_join import (
18+
ExperimentJoinDbAdapter,
19+
)
20+
from autosubmit_api.database.adapters.job_packages import (
21+
JobPackagesDbAdapter,
22+
WrapperJobPackagesDbAdapter,
23+
)
1824

1925

2026
__all__ = [
2127
"ExperimentDbAdapter",
2228
"ExperimentDetailsDbAdapter",
2329
"ExperimentStatusDbAdapter",
2430
"ExpGraphDrawDBAdapter",
25-
"ExperimentJoinDbAdapter"
31+
"ExperimentJoinDbAdapter",
32+
"JobPackagesDbAdapter",
33+
"WrapperJobPackagesDbAdapter",
2634
]

autosubmit_api/database/adapters/experiment.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ def __init__(self):
1212
db_filepath=APIBasicConfig.DB_PATH,
1313
)
1414

15+
def create_table(self):
16+
"""
17+
Create the experiment table.
18+
"""
19+
with self.table_manager.get_connection() as conn:
20+
self.table_manager.create_table(conn)
21+
1522
def get_all(self):
1623
"""
1724
Return all experiments.

autosubmit_api/database/adapters/experiment_details.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,37 @@ def __init__(self) -> None:
1212
db_filepath=APIBasicConfig.DB_PATH,
1313
)
1414

15+
def create_table(self):
16+
"""
17+
Create the details table.
18+
"""
19+
with self.table_manager.get_connection() as conn:
20+
self.table_manager.create_table(conn)
21+
1522
def delete_all(self) -> int:
23+
"""
24+
Clear the details table.
25+
"""
1626
with self.table_manager.get_connection() as conn:
1727
rowcount = self.table_manager.delete_all(conn)
1828
return rowcount
1929

2030
def insert_many(self, values: List[Dict[str, Any]]) -> int:
31+
"""
32+
Insert many rows into the details table.
33+
"""
2134
with self.table_manager.get_connection() as conn:
2235
rowcount = self.table_manager.insert_many(conn, values)
2336
return rowcount
37+
38+
def get_by_exp_id(self, exp_id: int) -> Dict[str, Any]:
39+
"""
40+
Get experiment details by the numerical exp_id.
41+
"""
42+
with self.table_manager.get_connection() as conn:
43+
row = conn.execute(
44+
self.table_manager.table.select().where(
45+
tables.DetailsTable.exp_id == exp_id
46+
)
47+
).one()
48+
return row._mapping

autosubmit_api/database/adapters/experiment_status.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from datetime import datetime
22
import os
3-
from typing import Dict
3+
from typing import Dict, List
44
from autosubmit.database.db_manager import create_db_table_manager
55
from sqlalchemy import delete, insert, select
66
from autosubmit_api.config.basicConfig import APIBasicConfig
@@ -15,6 +15,13 @@ def __init__(self) -> None:
1515
db_filepath=os.path.join(APIBasicConfig.DB_DIR, APIBasicConfig.AS_TIMES_DB),
1616
)
1717

18+
def create_table(self):
19+
"""
20+
Create the experiment_status table.
21+
"""
22+
with self.table_manager.get_connection() as conn:
23+
self.table_manager.create_table(conn)
24+
1825
def get_all_dict(self) -> Dict[str, str]:
1926
"""
2027
Gets table experiment_status as dictionary {expid: status}
@@ -26,6 +33,18 @@ def get_all_dict(self) -> Dict[str, str]:
2633
result[row.name] = row.status
2734
return result
2835

36+
def get_only_running_expids(self) -> List[str]:
37+
"""
38+
Gets list of running experiments
39+
"""
40+
with self.table_manager.get_connection() as conn:
41+
rows = conn.execute(
42+
select(self.table_manager.table).where(
43+
self.table_manager.table.c.status == "RUNNING"
44+
)
45+
).all()
46+
return [row.name for row in rows]
47+
2948
def get_status(self, expid: str) -> str:
3049
"""
3150
Gets the current status of one experiment
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from typing import Dict, List
2+
from autosubmit.database.db_manager import create_db_table_manager
3+
from sqlalchemy import select
4+
5+
from autosubmit_api.database import tables
6+
from autosubmit_api.persistance.experiment import ExperimentPaths
7+
8+
9+
class JobPackagesDbAdapter:
10+
def __init__(self, expid: str) -> None:
11+
self.expid = expid
12+
self.table_manager = create_db_table_manager(
13+
table=tables.JobPackageTable,
14+
db_filepath=ExperimentPaths(expid).job_packages_db,
15+
schema=expid,
16+
)
17+
18+
def get_all(self) -> List[Dict[str, str]]:
19+
"""
20+
Get all job packages.
21+
"""
22+
with self.table_manager.get_connection() as conn:
23+
rows = conn.execute(select(self.table_manager.table)).all()
24+
return [row._mapping for row in rows]
25+
26+
27+
class WrapperJobPackagesDbAdapter:
28+
def __init__(self, expid: str) -> None:
29+
self.expid = expid
30+
self.table_manager = create_db_table_manager(
31+
table=tables.WrapperJobPackageTable,
32+
db_filepath=ExperimentPaths(expid).job_packages_db,
33+
schema=expid,
34+
)
35+
36+
def get_all(self) -> List[Dict[str, str]]:
37+
"""
38+
Get all job packages.
39+
"""
40+
with self.table_manager.get_connection() as conn:
41+
rows = conn.execute(select(self.table_manager.table)).all()
42+
return [row._mapping for row in rows]

autosubmit_api/database/common.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ def get_postgres_engine():
2323
class AttachedDatabaseConnBuilder(BaseBuilder):
2424
"""
2525
SQLite utility to build attached databases.
26+
27+
MUST BE USED ONLY FOR ADAPTERS and TESTS.
2628
"""
2729

2830
def __init__(self) -> None:
@@ -52,6 +54,8 @@ def product(self) -> Connection:
5254
def create_main_db_conn() -> Connection:
5355
"""
5456
Connection with the autosubmit and as_times DDBB.
57+
58+
MUST BE USED ONLY FOR ADAPTERS and TESTS.
5559
"""
5660
APIBasicConfig.read()
5761
if APIBasicConfig.DATABASE_BACKEND == "postgres":
@@ -66,6 +70,8 @@ def create_main_db_conn() -> Connection:
6670
def create_autosubmit_db_engine() -> Engine:
6771
"""
6872
Create an engine for the autosubmit DDBB. Usually named autosubmit.db
73+
74+
MUST BE USED ONLY FOR ADAPTERS and TESTS.
6975
"""
7076
APIBasicConfig.read()
7177
if APIBasicConfig.DATABASE_BACKEND == "postgres":
@@ -78,6 +84,8 @@ def create_autosubmit_db_engine() -> Engine:
7884
def create_as_times_db_engine() -> Engine:
7985
"""
8086
Create an engine for the AS_TIMES DDBB. Usually named as_times.db
87+
88+
MUST BE USED ONLY FOR ADAPTERS and TESTS.
8189
"""
8290

8391
APIBasicConfig.read()

autosubmit_api/database/db_jobdata.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ def __init__(self, expid: str, basic_config: APIBasicConfig):
513513
self.db_version = self._select_pragma_version()
514514
# self.query_job_historic = None
515515
# Historic only working on DB 12 now
516-
self.query_job_historic = "SELECT id, counter, job_name, created, modified, submit, start, finish, status, rowtype, ncpus, wallclock, qos, energy, date, section, member, chunk, last, platform, job_id, extra_data, nnodes, run_id FROM job_data WHERE job_name=? ORDER BY counter DESC"
516+
# self.query_job_historic = "SELECT id, counter, job_name, created, modified, submit, start, finish, status, rowtype, ncpus, wallclock, qos, energy, date, section, member, chunk, last, platform, job_id, extra_data, nnodes, run_id FROM job_data WHERE job_name=? ORDER BY counter DESC"
517517

518518
if self.db_version < DB_VERSION_SCHEMA_CHANGES:
519519
try:

autosubmit_api/persistance/job_package_reader.py

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
from typing import Dict, List
2-
from sqlalchemy import select
2+
from autosubmit_api.database.adapters import (
3+
JobPackagesDbAdapter,
4+
WrapperJobPackagesDbAdapter,
5+
)
36
from autosubmit_api.logger import logger
4-
from autosubmit_api.database import tables
5-
from autosubmit_api.database.common import AttachedDatabaseConnBuilder
6-
from autosubmit_api.persistance.experiment import ExperimentPaths
77

88

99
class JobPackageReader:
10-
1110
def __init__(self, expid: str) -> None:
1211
self.expid = expid
1312
self._content: List[Dict] = []
@@ -17,23 +16,13 @@ def __init__(self, expid: str) -> None:
1716
self._package_to_symbol: Dict[str, str] = {}
1817

1918
def read(self):
20-
conn_builder = AttachedDatabaseConnBuilder()
21-
conn_builder.attach_db(
22-
ExperimentPaths(self.expid).job_packages_db, "job_packages"
23-
)
24-
25-
with conn_builder.product as conn:
26-
try:
27-
statement = select(tables.JobPackageTable)
28-
self._content = [x._mapping for x in conn.execute(statement).all()]
29-
if len(self._content) == 0:
30-
raise Warning(
31-
"job_packages table empty, trying wrapper_job_packages"
32-
)
33-
except Exception as exc:
34-
logger.warning(exc)
35-
statement = select(tables.WrapperJobPackageTable)
36-
self._content = [x._mapping for x in conn.execute(statement).all()]
19+
try:
20+
self._content = JobPackagesDbAdapter(self.expid).get_all()
21+
if len(self._content) == 0:
22+
raise Warning("job_packages table empty, trying wrapper_job_packages")
23+
except Exception as exc:
24+
logger.warning(exc)
25+
self._content = WrapperJobPackagesDbAdapter(self.expid).get_all()
3726

3827
self._build_job_to_package()
3928
self._build_package_to_jobs()

0 commit comments

Comments
 (0)