diracx-db 0.0.1a27__py3-none-any.whl → 0.0.1a28__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- diracx/db/os/utils.py +5 -3
- diracx/db/sql/auth/db.py +39 -73
- diracx/db/sql/job/db.py +30 -123
- diracx/db/sql/job_logging/db.py +21 -81
- diracx/db/sql/sandbox_metadata/db.py +14 -15
- diracx/db/sql/task_queue/db.py +43 -124
- diracx/db/sql/utils/__init__.py +2 -1
- diracx/db/sql/utils/base.py +2 -2
- diracx/db/sql/utils/functions.py +5 -0
- {diracx_db-0.0.1a27.dist-info → diracx_db-0.0.1a28.dist-info}/METADATA +1 -3
- {diracx_db-0.0.1a27.dist-info → diracx_db-0.0.1a28.dist-info}/RECORD +14 -15
- {diracx_db-0.0.1a27.dist-info → diracx_db-0.0.1a28.dist-info}/entry_points.txt +2 -2
- diracx/db/sql/utils/job.py +0 -578
- {diracx_db-0.0.1a27.dist-info → diracx_db-0.0.1a28.dist-info}/WHEEL +0 -0
- {diracx_db-0.0.1a27.dist-info → diracx_db-0.0.1a28.dist-info}/top_level.txt +0 -0
diracx/db/sql/task_queue/db.py
CHANGED
@@ -7,8 +7,6 @@ from sqlalchemy import delete, func, select, update
|
|
7
7
|
if TYPE_CHECKING:
|
8
8
|
pass
|
9
9
|
|
10
|
-
from diracx.core.properties import JOB_SHARING, SecurityProperty
|
11
|
-
|
12
10
|
from ..utils import BaseSQLDB
|
13
11
|
from .schema import (
|
14
12
|
BannedSitesQueue,
|
@@ -49,126 +47,23 @@ class TaskQueueDB(BaseSQLDB):
|
|
49
47
|
)
|
50
48
|
return dict((await self.conn.execute(stmt)).one()._mapping)
|
51
49
|
|
52
|
-
async def
|
53
|
-
"""
|
54
|
-
stmt = delete(JobsQueue).where(JobsQueue.JobId == job_id)
|
55
|
-
await self.conn.execute(stmt)
|
56
|
-
|
57
|
-
async def remove_jobs(self, job_ids: list[int]):
|
58
|
-
"""Remove jobs from the task queues."""
|
59
|
-
stmt = delete(JobsQueue).where(JobsQueue.JobId.in_(job_ids))
|
60
|
-
await self.conn.execute(stmt)
|
61
|
-
|
62
|
-
async def delete_task_queue_if_empty(
|
63
|
-
self,
|
64
|
-
tq_id: int,
|
65
|
-
tq_owner: str,
|
66
|
-
tq_group: str,
|
67
|
-
job_share: int,
|
68
|
-
group_properties: set[SecurityProperty],
|
69
|
-
enable_shares_correction: bool,
|
70
|
-
allow_background_tqs: bool,
|
71
|
-
):
|
72
|
-
"""Try to delete a task queue if it's empty."""
|
73
|
-
# Check if the task queue is empty
|
74
|
-
stmt = (
|
75
|
-
select(TaskQueues.TQId)
|
76
|
-
.where(TaskQueues.Enabled >= 1)
|
77
|
-
.where(TaskQueues.TQId == tq_id)
|
78
|
-
.where(~TaskQueues.TQId.in_(select(JobsQueue.TQId)))
|
79
|
-
)
|
80
|
-
rows = await self.conn.execute(stmt)
|
81
|
-
if not rows.rowcount:
|
82
|
-
return
|
83
|
-
|
84
|
-
# Deleting the task queue (the other tables will be deleted in cascade)
|
85
|
-
stmt = delete(TaskQueues).where(TaskQueues.TQId == tq_id)
|
86
|
-
await self.conn.execute(stmt)
|
87
|
-
|
88
|
-
await self.recalculate_tq_shares_for_entity(
|
89
|
-
tq_owner,
|
90
|
-
tq_group,
|
91
|
-
job_share,
|
92
|
-
group_properties,
|
93
|
-
enable_shares_correction,
|
94
|
-
allow_background_tqs,
|
95
|
-
)
|
96
|
-
|
97
|
-
async def recalculate_tq_shares_for_entity(
|
98
|
-
self,
|
99
|
-
owner: str,
|
100
|
-
group: str,
|
101
|
-
job_share: int,
|
102
|
-
group_properties: set[SecurityProperty],
|
103
|
-
enable_shares_correction: bool,
|
104
|
-
allow_background_tqs: bool,
|
105
|
-
):
|
106
|
-
"""Recalculate the shares for a user/userGroup combo."""
|
107
|
-
if JOB_SHARING in group_properties:
|
108
|
-
# If group has JobSharing just set prio for that entry, user is irrelevant
|
109
|
-
return await self.__set_priorities_for_entity(
|
110
|
-
owner, group, job_share, group_properties, allow_background_tqs
|
111
|
-
)
|
112
|
-
|
50
|
+
async def get_task_queue_owners_by_group(self, group: str) -> dict[str, int]:
|
51
|
+
"""Get the owners for a task queue and group."""
|
113
52
|
stmt = (
|
114
53
|
select(TaskQueues.Owner, func.count(TaskQueues.Owner))
|
115
54
|
.where(TaskQueues.OwnerGroup == group)
|
116
55
|
.group_by(TaskQueues.Owner)
|
117
56
|
)
|
118
57
|
rows = await self.conn.execute(stmt)
|
119
|
-
# make the rows a list of tuples
|
120
58
|
# Get owners in this group and the amount of times they appear
|
121
59
|
# TODO: I guess the rows are already a list of tupes
|
122
60
|
# maybe refactor
|
123
|
-
|
124
|
-
num_owners = len(data)
|
125
|
-
# If there are no owners do now
|
126
|
-
if num_owners == 0:
|
127
|
-
return
|
128
|
-
# Split the share amongst the number of owners
|
129
|
-
entities_shares = {row[0]: job_share / num_owners for row in data}
|
130
|
-
|
131
|
-
# TODO: implement the following
|
132
|
-
# If corrector is enabled let it work it's magic
|
133
|
-
# if enable_shares_correction:
|
134
|
-
# entities_shares = await self.__shares_corrector.correct_shares(
|
135
|
-
# entitiesShares, group=group
|
136
|
-
# )
|
137
|
-
|
138
|
-
# Keep updating
|
139
|
-
owners = dict(data)
|
140
|
-
# IF the user is already known and has more than 1 tq, the rest of the users don't need to be modified
|
141
|
-
# (The number of owners didn't change)
|
142
|
-
if owner in owners and owners[owner] > 1:
|
143
|
-
await self.__set_priorities_for_entity(
|
144
|
-
owner,
|
145
|
-
group,
|
146
|
-
entities_shares[owner],
|
147
|
-
group_properties,
|
148
|
-
allow_background_tqs,
|
149
|
-
)
|
150
|
-
return
|
151
|
-
# Oops the number of owners may have changed so we recalculate the prio for all owners in the group
|
152
|
-
for owner in owners:
|
153
|
-
await self.__set_priorities_for_entity(
|
154
|
-
owner,
|
155
|
-
group,
|
156
|
-
entities_shares[owner],
|
157
|
-
group_properties,
|
158
|
-
allow_background_tqs,
|
159
|
-
)
|
160
|
-
|
161
|
-
async def __set_priorities_for_entity(
|
162
|
-
self,
|
163
|
-
owner: str,
|
164
|
-
group: str,
|
165
|
-
share,
|
166
|
-
properties: set[SecurityProperty],
|
167
|
-
allow_background_tqs: bool,
|
168
|
-
):
|
169
|
-
"""Set the priority for a user/userGroup combo given a splitted share."""
|
170
|
-
from DIRAC.WorkloadManagementSystem.DB.TaskQueueDB import calculate_priority
|
61
|
+
return {r[0]: r[1] for r in rows if r}
|
171
62
|
|
63
|
+
async def get_task_queue_priorities(
|
64
|
+
self, group: str, owner: str | None = None
|
65
|
+
) -> dict[int, float]:
|
66
|
+
"""Get the priorities for a list of task queues."""
|
172
67
|
stmt = (
|
173
68
|
select(
|
174
69
|
TaskQueues.TQId,
|
@@ -178,24 +73,48 @@ class TaskQueueDB(BaseSQLDB):
|
|
178
73
|
.where(TaskQueues.OwnerGroup == group)
|
179
74
|
.group_by(TaskQueues.TQId)
|
180
75
|
)
|
181
|
-
if
|
76
|
+
if owner:
|
182
77
|
stmt = stmt.where(TaskQueues.Owner == owner)
|
183
78
|
rows = await self.conn.execute(stmt)
|
184
|
-
|
79
|
+
return {tq_id: priority for tq_id, priority in rows}
|
185
80
|
|
186
|
-
|
187
|
-
|
81
|
+
async def remove_jobs(self, job_ids: list[int]):
|
82
|
+
"""Remove jobs from the task queues."""
|
83
|
+
stmt = delete(JobsQueue).where(JobsQueue.JobId.in_(job_ids))
|
84
|
+
await self.conn.execute(stmt)
|
188
85
|
|
189
|
-
|
86
|
+
async def is_task_queue_empty(self, tq_id: int) -> bool:
|
87
|
+
"""Check if a task queue is empty."""
|
88
|
+
stmt = (
|
89
|
+
select(TaskQueues.TQId)
|
90
|
+
.where(TaskQueues.Enabled >= 1)
|
91
|
+
.where(TaskQueues.TQId == tq_id)
|
92
|
+
.where(~TaskQueues.TQId.in_(select(JobsQueue.TQId)))
|
93
|
+
)
|
94
|
+
rows = await self.conn.execute(stmt)
|
95
|
+
return not rows.rowcount
|
190
96
|
|
191
|
-
|
97
|
+
async def delete_task_queue(
|
98
|
+
self,
|
99
|
+
tq_id: int,
|
100
|
+
):
|
101
|
+
"""Delete a task queue."""
|
102
|
+
# Deleting the task queue (the other tables will be deleted in cascade)
|
103
|
+
stmt = delete(TaskQueues).where(TaskQueues.TQId == tq_id)
|
104
|
+
await self.conn.execute(stmt)
|
192
105
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
106
|
+
async def set_priorities_for_entity(
|
107
|
+
self,
|
108
|
+
tq_ids: list[int],
|
109
|
+
priority: float,
|
110
|
+
):
|
111
|
+
"""Set the priority for a user/userGroup combo given a splitted share."""
|
112
|
+
update_stmt = (
|
113
|
+
update(TaskQueues)
|
114
|
+
.where(TaskQueues.TQId.in_(tq_ids))
|
115
|
+
.values(Priority=priority)
|
116
|
+
)
|
117
|
+
await self.conn.execute(update_stmt)
|
199
118
|
|
200
119
|
async def retrieve_task_queues(self, tq_id_list=None):
|
201
120
|
"""Get all the task queues."""
|
diracx/db/sql/utils/__init__.py
CHANGED
@@ -6,7 +6,7 @@ from .base import (
|
|
6
6
|
apply_search_filters,
|
7
7
|
apply_sort_constraints,
|
8
8
|
)
|
9
|
-
from .functions import substract_date, utcnow
|
9
|
+
from .functions import hash, substract_date, utcnow
|
10
10
|
from .types import Column, DateNowColumn, EnumBackedBool, EnumColumn, NullColumn
|
11
11
|
|
12
12
|
__all__ = (
|
@@ -20,5 +20,6 @@ __all__ = (
|
|
20
20
|
"apply_search_filters",
|
21
21
|
"apply_sort_constraints",
|
22
22
|
"substract_date",
|
23
|
+
"hash",
|
23
24
|
"SQLDBUnavailableError",
|
24
25
|
)
|
diracx/db/sql/utils/base.py
CHANGED
@@ -104,7 +104,7 @@ class BaseSQLDB(metaclass=ABCMeta):
|
|
104
104
|
db_classes: list[type[BaseSQLDB]] = [
|
105
105
|
entry_point.load()
|
106
106
|
for entry_point in select_from_extension(
|
107
|
-
group="diracx.
|
107
|
+
group="diracx.dbs.sql", name=db_name
|
108
108
|
)
|
109
109
|
]
|
110
110
|
if not db_classes:
|
@@ -119,7 +119,7 @@ class BaseSQLDB(metaclass=ABCMeta):
|
|
119
119
|
prefixed with ``DIRACX_DB_URL_{DB_NAME}``.
|
120
120
|
"""
|
121
121
|
db_urls: dict[str, str] = {}
|
122
|
-
for entry_point in select_from_extension(group="diracx.
|
122
|
+
for entry_point in select_from_extension(group="diracx.dbs.sql"):
|
123
123
|
db_name = entry_point.name
|
124
124
|
var_name = f"DIRACX_DB_URL_{entry_point.name.upper()}"
|
125
125
|
if var_name in os.environ:
|
diracx/db/sql/utils/functions.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
import hashlib
|
3
4
|
from datetime import datetime, timedelta, timezone
|
4
5
|
from typing import TYPE_CHECKING
|
5
6
|
|
@@ -104,3 +105,7 @@ def sqlite_date_trunc(element, compiler, **kw):
|
|
104
105
|
|
105
106
|
def substract_date(**kwargs: float) -> datetime:
|
106
107
|
return datetime.now(tz=timezone.utc) - timedelta(**kwargs)
|
108
|
+
|
109
|
+
|
110
|
+
def hash(code: str):
|
111
|
+
return hashlib.sha256(code.encode()).hexdigest()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: diracx-db
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.1a28
|
4
4
|
Summary: TODO
|
5
5
|
License: GPL-3.0-only
|
6
6
|
Classifier: Intended Audience :: Science/Research
|
@@ -10,9 +10,7 @@ Classifier: Topic :: Scientific/Engineering
|
|
10
10
|
Classifier: Topic :: System :: Distributed Computing
|
11
11
|
Requires-Python: >=3.11
|
12
12
|
Description-Content-Type: text/markdown
|
13
|
-
Requires-Dist: dirac
|
14
13
|
Requires-Dist: diracx-core
|
15
|
-
Requires-Dist: fastapi
|
16
14
|
Requires-Dist: opensearch-py[async]
|
17
15
|
Requires-Dist: pydantic>=2.10
|
18
16
|
Requires-Dist: sqlalchemy[aiomysql,aiosqlite]>=2
|
@@ -4,36 +4,35 @@ diracx/db/exceptions.py,sha256=1nn-SZLG-nQwkxbvHjZqXhE5ouzWj1f3qhSda2B4ZEg,83
|
|
4
4
|
diracx/db/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
diracx/db/os/__init__.py,sha256=IZr6z6SefrRvuC8sTC4RmB3_wwOyEt1GzpDuwSMH8O4,112
|
6
6
|
diracx/db/os/job_parameters.py,sha256=Knca19uT2G-5FI7MOFlaOAXeHn4ecPVLIH30TiwhaTw,858
|
7
|
-
diracx/db/os/utils.py,sha256=
|
7
|
+
diracx/db/os/utils.py,sha256=xQLhOgC9YidfeEIbmdigXg3_YZLKHwMcZzhHf4mRwyQ,11399
|
8
8
|
diracx/db/sql/__init__.py,sha256=JYu0b0IVhoXy3lX2m2r2dmAjsRS7IbECBUMEDvX0Te4,391
|
9
9
|
diracx/db/sql/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
-
diracx/db/sql/auth/db.py,sha256=
|
10
|
+
diracx/db/sql/auth/db.py,sha256=O9sp-AKobQ4X4IF2WaJKig-8LU8Ra9Syn5jW8JNLRU4,9030
|
11
11
|
diracx/db/sql/auth/schema.py,sha256=-yXVfNz45W3VvvrNf-ZrSzIgb9qMaI9x1fWDshSkpPU,3141
|
12
12
|
diracx/db/sql/dummy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
diracx/db/sql/dummy/db.py,sha256=whcF02IjFQTwe1l4iTHtCkg2XukEaLHpLeHYNGMuGGw,1645
|
14
14
|
diracx/db/sql/dummy/schema.py,sha256=9zI53pKlzc6qBezsyjkatOQrNZdGCjwgjQ8Iz_pyAXs,789
|
15
15
|
diracx/db/sql/job/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
|
-
diracx/db/sql/job/db.py,sha256=
|
16
|
+
diracx/db/sql/job/db.py,sha256=qoK1toWekRP1BO5XbT9CaRuGKR9_oixMVfRZ9myZsjg,8644
|
17
17
|
diracx/db/sql/job/schema.py,sha256=Rmt5ldVN6Pf4MJHMhiT_Zn-k9LVPBTVivmGlyPKFRZE,4647
|
18
18
|
diracx/db/sql/job_logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
-
diracx/db/sql/job_logging/db.py,sha256
|
19
|
+
diracx/db/sql/job_logging/db.py,sha256=0WuRn3pKEeuV9IZ_3VDhlvqI9eM1W4C0dZwIVZKW9N8,5811
|
20
20
|
diracx/db/sql/job_logging/schema.py,sha256=DyFr_4goxfC453xPJX4OkxTGHtlP_5q8PXpr8bhNQS0,960
|
21
21
|
diracx/db/sql/pilot_agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
22
|
diracx/db/sql/pilot_agents/db.py,sha256=7-cuCbh_KhM0jlybsHMWV-W66bHsPHIVBpbuqwjncj0,1232
|
23
23
|
diracx/db/sql/pilot_agents/schema.py,sha256=KeWnFSpYOTrT3-_rOCFjbjNnPNXKnUZiJVsu4vv5U2U,2149
|
24
24
|
diracx/db/sql/sandbox_metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
-
diracx/db/sql/sandbox_metadata/db.py,sha256=
|
25
|
+
diracx/db/sql/sandbox_metadata/db.py,sha256=IyQtTIxRzRv0cdhR3Of1uVzliggePY67bz_9HeKIOjE,6666
|
26
26
|
diracx/db/sql/sandbox_metadata/schema.py,sha256=mI-YpH6NneOQ6QiqwIwyJ4afwfoamybSlQpvaISFfPY,1431
|
27
27
|
diracx/db/sql/task_queue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
|
-
diracx/db/sql/task_queue/db.py,sha256=
|
28
|
+
diracx/db/sql/task_queue/db.py,sha256=Ymd9cBasiSAPmgu5846B8KmguRiJ_GoJhuOev9YwW2o,6248
|
29
29
|
diracx/db/sql/task_queue/schema.py,sha256=5efAgvNYRkLlaJ2NzRInRfmVa3tyIzQu2l0oRPy4Kzw,3258
|
30
|
-
diracx/db/sql/utils/__init__.py,sha256=
|
31
|
-
diracx/db/sql/utils/base.py,sha256=
|
32
|
-
diracx/db/sql/utils/functions.py,sha256=
|
33
|
-
diracx/db/sql/utils/job.py,sha256=U_y8DZdMGU5NbQF3udA4Yg43HaKhF8YhYa-PhzYmIyI,19592
|
30
|
+
diracx/db/sql/utils/__init__.py,sha256=QkvpqBuIAgkAOywAssYzdxSzUQVZlSUumK7mPxotXfM,547
|
31
|
+
diracx/db/sql/utils/base.py,sha256=7UxHBNLOSjdrIdslMKW4C_c5H9-6Y1BEimxscri2poE,12367
|
32
|
+
diracx/db/sql/utils/functions.py,sha256=iLqlUIQ6SrDUtDEnZ5szaFbdcINJW15KNbCdGXss6kc,3055
|
34
33
|
diracx/db/sql/utils/types.py,sha256=yU-tXsu6hFGPsr9ba1n3ZjGPnHQI_06lbpkTeDCWJtg,1287
|
35
|
-
diracx_db-0.0.
|
36
|
-
diracx_db-0.0.
|
37
|
-
diracx_db-0.0.
|
38
|
-
diracx_db-0.0.
|
39
|
-
diracx_db-0.0.
|
34
|
+
diracx_db-0.0.1a28.dist-info/METADATA,sha256=7tBHb4St4d0QeFQEBqfMYGTxhXaIOP2K2evK0GvJHCo,644
|
35
|
+
diracx_db-0.0.1a28.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
36
|
+
diracx_db-0.0.1a28.dist-info/entry_points.txt,sha256=UPqhLvb9gui0kOyWeI_edtefcrHToZmQt1p76vIwujo,317
|
37
|
+
diracx_db-0.0.1a28.dist-info/top_level.txt,sha256=vJx10tdRlBX3rF2Psgk5jlwVGZNcL3m_7iQWwgPXt-U,7
|
38
|
+
diracx_db-0.0.1a28.dist-info/RECORD,,
|