diracx-db 0.0.1a34__tar.gz → 0.0.1a35__tar.gz
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-0.0.1a34 → diracx_db-0.0.1a35}/PKG-INFO +1 -1
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/os/job_parameters.py +15 -4
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/os/utils.py +10 -5
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/job/db.py +23 -2
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/job/schema.py +32 -5
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx_db.egg-info/PKG-INFO +1 -1
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/opensearch/test_index_template.py +3 -2
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/opensearch/test_search.py +3 -3
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/README.md +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/pyproject.toml +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/setup.cfg +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/__main__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/exceptions.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/os/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/py.typed +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/auth/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/auth/db.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/auth/schema.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/dummy/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/dummy/db.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/dummy/schema.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/job/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/job_logging/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/job_logging/db.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/job_logging/schema.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/pilot_agents/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/pilot_agents/db.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/pilot_agents/schema.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/sandbox_metadata/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/sandbox_metadata/db.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/sandbox_metadata/schema.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/task_queue/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/task_queue/db.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/task_queue/schema.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/utils/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/utils/base.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/utils/functions.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx/db/sql/utils/types.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx_db.egg-info/SOURCES.txt +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx_db.egg-info/dependency_links.txt +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx_db.egg-info/entry_points.txt +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx_db.egg-info/requires.txt +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/src/diracx_db.egg-info/top_level.txt +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/auth/test_authorization_flow.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/auth/test_device_flow.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/auth/test_refresh_token.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/jobs/test_job_db.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/jobs/test_job_logging_db.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/jobs/test_sandbox_metadata.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/opensearch/test_connection.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/pilot_agents/__init__.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/pilot_agents/test_pilot_agents_db.py +0 -0
- {diracx_db-0.0.1a34 → diracx_db-0.0.1a35}/tests/test_dummy_db.py +0 -0
@@ -1,5 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
from DIRAC.Core.Utilities import TimeUtilities
|
4
|
+
|
3
5
|
from diracx.db.os.utils import BaseOSDB
|
4
6
|
|
5
7
|
|
@@ -18,8 +20,17 @@ class JobParametersDB(BaseOSDB):
|
|
18
20
|
"Status": {"type": "keyword"},
|
19
21
|
"JobType": {"type": "keyword"},
|
20
22
|
}
|
21
|
-
|
23
|
+
# TODO: Does this need to be configurable?
|
24
|
+
index_prefix = "job_parameters"
|
25
|
+
|
26
|
+
def index_name(self, vo, doc_id: int) -> str:
|
27
|
+
split = int(int(doc_id) // 1e6)
|
28
|
+
return f"{self.index_prefix}_{vo}_{split}m"
|
22
29
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
30
|
+
def upsert(self, vo, doc_id, document):
|
31
|
+
document = {
|
32
|
+
"JobID": doc_id,
|
33
|
+
"timestamp": TimeUtilities.toEpochMilliSeconds(),
|
34
|
+
**document,
|
35
|
+
}
|
36
|
+
return super().upsert(vo, doc_id, document)
|
@@ -77,7 +77,7 @@ class BaseOSDB(metaclass=ABCMeta):
|
|
77
77
|
index_prefix: str
|
78
78
|
|
79
79
|
@abstractmethod
|
80
|
-
def index_name(self, doc_id: int) -> str: ...
|
80
|
+
def index_name(self, vo: str, doc_id: int) -> str: ...
|
81
81
|
|
82
82
|
def __init__(self, connection_kwargs: dict[str, Any]) -> None:
|
83
83
|
self._client: AsyncOpenSearch | None = None
|
@@ -182,15 +182,20 @@ class BaseOSDB(metaclass=ABCMeta):
|
|
182
182
|
)
|
183
183
|
assert result["acknowledged"]
|
184
184
|
|
185
|
-
async def upsert(self, doc_id, document) -> None:
|
186
|
-
|
185
|
+
async def upsert(self, vo: str, doc_id: int, document: Any) -> None:
|
186
|
+
index_name = self.index_name(vo, doc_id)
|
187
187
|
response = await self.client.update(
|
188
|
-
index=
|
188
|
+
index=index_name,
|
189
189
|
id=doc_id,
|
190
190
|
body={"doc": document, "doc_as_upsert": True},
|
191
191
|
params=dict(retry_on_conflict=10),
|
192
192
|
)
|
193
|
-
|
193
|
+
logger.debug(
|
194
|
+
"Upserted document %s in index %s with response: %s",
|
195
|
+
doc_id,
|
196
|
+
index_name,
|
197
|
+
response,
|
198
|
+
)
|
194
199
|
|
195
200
|
async def search(
|
196
201
|
self, parameters, search, sorts, *, per_page: int = 100, page: int | None = None
|
@@ -167,6 +167,24 @@ class JobDB(BaseSQLDB):
|
|
167
167
|
],
|
168
168
|
)
|
169
169
|
|
170
|
+
@staticmethod
|
171
|
+
def _set_job_attributes_fix_value(column, value):
|
172
|
+
"""Apply corrections to the values before inserting them into the database.
|
173
|
+
|
174
|
+
TODO: Move this logic into the sqlalchemy model.
|
175
|
+
"""
|
176
|
+
if column == "VerifiedFlag":
|
177
|
+
value_str = str(value)
|
178
|
+
if value_str in ("True", "False"):
|
179
|
+
return value_str
|
180
|
+
if column == "AccountedFlag":
|
181
|
+
value_str = str(value)
|
182
|
+
if value_str in ("True", "False", "Failed"):
|
183
|
+
return value_str
|
184
|
+
else:
|
185
|
+
return value
|
186
|
+
raise NotImplementedError(f"Unrecognized value for column {column}: {value}")
|
187
|
+
|
170
188
|
async def set_job_attributes(self, job_data):
|
171
189
|
"""Update the parameters of the given jobs."""
|
172
190
|
# TODO: add myDate and force parameters.
|
@@ -179,7 +197,10 @@ class JobDB(BaseSQLDB):
|
|
179
197
|
case_expressions = {
|
180
198
|
column: case(
|
181
199
|
*[
|
182
|
-
(
|
200
|
+
(
|
201
|
+
Jobs.__table__.c.JobID == job_id,
|
202
|
+
self._set_job_attributes_fix_value(column, attrs[column]),
|
203
|
+
)
|
183
204
|
for job_id, attrs in job_data.items()
|
184
205
|
if column in attrs
|
185
206
|
],
|
@@ -309,6 +330,6 @@ class JobDB(BaseSQLDB):
|
|
309
330
|
await self.conn.execute(stmt)
|
310
331
|
# Return the commands grouped by job id
|
311
332
|
return [
|
312
|
-
JobCommand(job_id=cmd.
|
333
|
+
JobCommand(job_id=cmd.JobID, command=cmd.Command, arguments=cmd.Arguments)
|
313
334
|
for cmd in commands
|
314
335
|
]
|
@@ -1,8 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
+
import sqlalchemy.types as types
|
3
4
|
from sqlalchemy import (
|
4
5
|
DateTime,
|
5
|
-
Enum,
|
6
6
|
ForeignKey,
|
7
7
|
Index,
|
8
8
|
Integer,
|
@@ -16,6 +16,36 @@ from ..utils import Column, EnumBackedBool, NullColumn
|
|
16
16
|
JobDBBase = declarative_base()
|
17
17
|
|
18
18
|
|
19
|
+
class AccountedFlagEnum(types.TypeDecorator):
|
20
|
+
"""Maps a ``AccountedFlagEnum()`` column to True/False in Python."""
|
21
|
+
|
22
|
+
impl = types.Enum
|
23
|
+
cache_ok: bool = True
|
24
|
+
|
25
|
+
def __init__(self) -> None:
|
26
|
+
super().__init__("True", "False", "Failed")
|
27
|
+
|
28
|
+
def process_bind_param(self, value, dialect) -> str:
|
29
|
+
if value is True:
|
30
|
+
return "True"
|
31
|
+
elif value is False:
|
32
|
+
return "False"
|
33
|
+
elif value == "Failed":
|
34
|
+
return "Failed"
|
35
|
+
else:
|
36
|
+
raise NotImplementedError(value, dialect)
|
37
|
+
|
38
|
+
def process_result_value(self, value, dialect) -> bool | str:
|
39
|
+
if value == "True":
|
40
|
+
return True
|
41
|
+
elif value == "False":
|
42
|
+
return False
|
43
|
+
elif value == "Failed":
|
44
|
+
return "Failed"
|
45
|
+
else:
|
46
|
+
raise NotImplementedError(f"Unknown {value=}")
|
47
|
+
|
48
|
+
|
19
49
|
class Jobs(JobDBBase):
|
20
50
|
__tablename__ = "Jobs"
|
21
51
|
|
@@ -45,10 +75,7 @@ class Jobs(JobDBBase):
|
|
45
75
|
user_priority = Column("UserPriority", Integer, default=0)
|
46
76
|
reschedule_counter = Column("RescheduleCounter", Integer, default=0)
|
47
77
|
verified_flag = Column("VerifiedFlag", EnumBackedBool(), default=False)
|
48
|
-
|
49
|
-
accounted_flag = Column(
|
50
|
-
"AccountedFlag", Enum("True", "False", "Failed"), default="False"
|
51
|
-
)
|
78
|
+
accounted_flag = Column("AccountedFlag", AccountedFlagEnum(), default=False)
|
52
79
|
|
53
80
|
__table_args__ = (
|
54
81
|
Index("JobType", "JobType"),
|
@@ -31,15 +31,16 @@ async def dummy_opensearch_db_without_template(dummy_opensearch_db: DummyOSDB):
|
|
31
31
|
|
32
32
|
|
33
33
|
async def _get_test_index_mappings(dummy_opensearch_db: DummyOSDB):
|
34
|
+
vo = "dummyvo"
|
34
35
|
document_id = 1
|
35
|
-
index_name = dummy_opensearch_db.index_name(document_id)
|
36
|
+
index_name = dummy_opensearch_db.index_name(vo, document_id)
|
36
37
|
|
37
38
|
# At this point the index should not exist yet
|
38
39
|
with pytest.raises(opensearchpy.exceptions.NotFoundError):
|
39
40
|
await dummy_opensearch_db.client.indices.get_mapping(index_name)
|
40
41
|
|
41
42
|
# Insert document which will automatically create the index based on the template
|
42
|
-
await dummy_opensearch_db.upsert(document_id, DUMMY_DOCUMENT)
|
43
|
+
await dummy_opensearch_db.upsert(vo, document_id, DUMMY_DOCUMENT)
|
43
44
|
|
44
45
|
# Ensure the result looks as expected and return the mappings
|
45
46
|
index_mapping = await dummy_opensearch_db.client.indices.get_mapping(index_name)
|
@@ -104,9 +104,9 @@ async def prefilled_db(request):
|
|
104
104
|
"""Fill the database with dummy records for testing."""
|
105
105
|
impl = request.param
|
106
106
|
async with resolve_fixtures_hack(request, impl) as dummy_opensearch_db:
|
107
|
-
await dummy_opensearch_db.upsert(798811211, DOC1)
|
108
|
-
await dummy_opensearch_db.upsert(998811211, DOC2)
|
109
|
-
await dummy_opensearch_db.upsert(798811212, DOC3)
|
107
|
+
await dummy_opensearch_db.upsert("dummyvo", 798811211, DOC1)
|
108
|
+
await dummy_opensearch_db.upsert("dummyvo", 998811211, DOC2)
|
109
|
+
await dummy_opensearch_db.upsert("dummyvo", 798811212, DOC3)
|
110
110
|
|
111
111
|
# Force a refresh to make sure the documents are available
|
112
112
|
if not impl == "sql_opensearch_db":
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|