diracx-db 0.0.1a39__py3-none-any.whl → 0.0.1a41__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/sql/job_logging/db.py +14 -40
- diracx/db/sql/job_logging/schema.py +45 -10
- {diracx_db-0.0.1a39.dist-info → diracx_db-0.0.1a41.dist-info}/METADATA +1 -1
- {diracx_db-0.0.1a39.dist-info → diracx_db-0.0.1a41.dist-info}/RECORD +7 -7
- {diracx_db-0.0.1a39.dist-info → diracx_db-0.0.1a41.dist-info}/WHEEL +0 -0
- {diracx_db-0.0.1a39.dist-info → diracx_db-0.0.1a41.dist-info}/entry_points.txt +0 -0
- {diracx_db-0.0.1a39.dist-info → diracx_db-0.0.1a41.dist-info}/top_level.txt +0 -0
diracx/db/sql/job_logging/db.py
CHANGED
@@ -1,28 +1,15 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import
|
4
|
-
from datetime import timezone
|
5
|
-
from typing import
|
3
|
+
from collections import defaultdict
|
4
|
+
from datetime import datetime, timezone
|
5
|
+
from typing import Iterable
|
6
6
|
|
7
7
|
from sqlalchemy import delete, func, select
|
8
8
|
|
9
|
-
|
10
|
-
pass
|
11
|
-
|
12
|
-
from collections import defaultdict
|
13
|
-
|
14
|
-
from diracx.core.models import (
|
15
|
-
JobLoggingRecord,
|
16
|
-
JobStatusReturn,
|
17
|
-
)
|
9
|
+
from diracx.core.models import JobLoggingRecord, JobStatusReturn
|
18
10
|
|
19
11
|
from ..utils import BaseSQLDB
|
20
|
-
from .schema import
|
21
|
-
JobLoggingDBBase,
|
22
|
-
LoggingInfo,
|
23
|
-
)
|
24
|
-
|
25
|
-
MAGIC_EPOC_NUMBER = 1270000000
|
12
|
+
from .schema import JobLoggingDBBase, LoggingInfo
|
26
13
|
|
27
14
|
|
28
15
|
class JobLoggingDB(BaseSQLDB):
|
@@ -35,14 +22,6 @@ class JobLoggingDB(BaseSQLDB):
|
|
35
22
|
records: list[JobLoggingRecord],
|
36
23
|
):
|
37
24
|
"""Bulk insert entries to the JobLoggingDB table."""
|
38
|
-
|
39
|
-
def get_epoc(date):
|
40
|
-
return (
|
41
|
-
time.mktime(date.timetuple())
|
42
|
-
+ date.microsecond / 1000000.0
|
43
|
-
- MAGIC_EPOC_NUMBER
|
44
|
-
)
|
45
|
-
|
46
25
|
# First, fetch the maximum SeqNums for the given job_ids
|
47
26
|
seqnum_stmt = (
|
48
27
|
select(
|
@@ -70,7 +49,7 @@ class JobLoggingDB(BaseSQLDB):
|
|
70
49
|
"MinorStatus": record.minor_status,
|
71
50
|
"ApplicationStatus": record.application_status[:255],
|
72
51
|
"StatusTime": record.date,
|
73
|
-
"StatusTimeOrder":
|
52
|
+
"StatusTimeOrder": record.date,
|
74
53
|
"StatusSource": record.source[:32],
|
75
54
|
}
|
76
55
|
)
|
@@ -159,21 +138,16 @@ class JobLoggingDB(BaseSQLDB):
|
|
159
138
|
stmt = delete(LoggingInfo).where(LoggingInfo.job_id.in_(job_ids))
|
160
139
|
await self.conn.execute(stmt)
|
161
140
|
|
162
|
-
async def get_wms_time_stamps(
|
141
|
+
async def get_wms_time_stamps(
|
142
|
+
self, job_ids: Iterable[int]
|
143
|
+
) -> dict[int, dict[str, datetime]]:
|
163
144
|
"""Get TimeStamps for job MajorState transitions for multiple jobs at once
|
164
145
|
return a {JobID: {State:timestamp}} dictionary.
|
165
146
|
"""
|
166
|
-
result = defaultdict(dict)
|
147
|
+
result: defaultdict[int, dict[str, datetime]] = defaultdict(dict)
|
167
148
|
stmt = select(
|
168
|
-
LoggingInfo.job_id,
|
169
|
-
LoggingInfo.status,
|
170
|
-
LoggingInfo.status_time_order,
|
149
|
+
LoggingInfo.job_id, LoggingInfo.status, LoggingInfo.status_time_order
|
171
150
|
).where(LoggingInfo.job_id.in_(job_ids))
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
for job_id, event, etime in rows:
|
177
|
-
result[job_id][event] = str(etime + MAGIC_EPOC_NUMBER)
|
178
|
-
|
179
|
-
return result
|
151
|
+
for job_id, event, etime in await self.conn.execute(stmt):
|
152
|
+
result[job_id][event] = etime
|
153
|
+
return dict(result)
|
@@ -1,11 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from
|
4
|
-
|
5
|
-
|
6
|
-
PrimaryKeyConstraint,
|
7
|
-
String,
|
8
|
-
)
|
3
|
+
from datetime import UTC, datetime
|
4
|
+
|
5
|
+
from sqlalchemy import Integer, Numeric, PrimaryKeyConstraint, String, TypeDecorator
|
9
6
|
from sqlalchemy.orm import declarative_base
|
10
7
|
|
11
8
|
from ..utils import Column, DateNowColumn
|
@@ -13,6 +10,47 @@ from ..utils import Column, DateNowColumn
|
|
13
10
|
JobLoggingDBBase = declarative_base()
|
14
11
|
|
15
12
|
|
13
|
+
class MagicEpochDateTime(TypeDecorator):
|
14
|
+
"""A SQLAlchemy type that stores a datetime as a numeric value representing the
|
15
|
+
seconds elapsed since MAGIC_EPOC_NUMBER. The underlying column is defined as
|
16
|
+
Numeric(12,3) which provides a fixed-precision representation.
|
17
|
+
"""
|
18
|
+
|
19
|
+
impl = Numeric(12, 3)
|
20
|
+
cache_ok = True
|
21
|
+
|
22
|
+
MAGIC_EPOC_NUMBER = 1270000000
|
23
|
+
|
24
|
+
def process_bind_param(self, value, dialect):
|
25
|
+
"""Convert a Python datetime to a numeric value: (timestamp - MAGIC_EPOC_NUMBER).
|
26
|
+
The result is rounded to three decimal places.
|
27
|
+
"""
|
28
|
+
if value is None:
|
29
|
+
return None
|
30
|
+
if isinstance(value, datetime):
|
31
|
+
# Convert datetime to seconds since the Unix epoch, subtract our magic epoch,
|
32
|
+
# and round to three decimal places.
|
33
|
+
epoch_seconds = (
|
34
|
+
value.replace(tzinfo=UTC).timestamp() - self.MAGIC_EPOC_NUMBER
|
35
|
+
)
|
36
|
+
return round(epoch_seconds, 3)
|
37
|
+
raise ValueError(
|
38
|
+
"Expected a datetime object for MagicEpochDateTime bind parameter."
|
39
|
+
)
|
40
|
+
|
41
|
+
def process_result_value(self, value, dialect):
|
42
|
+
"""Convert the numeric database value back into a Python datetime by reversing the
|
43
|
+
stored difference (adding MAGIC_EPOC_NUMBER).
|
44
|
+
"""
|
45
|
+
if value is None:
|
46
|
+
return None
|
47
|
+
# Carefully convert from Decimal to datetime to avoid loosing precision
|
48
|
+
value += self.MAGIC_EPOC_NUMBER
|
49
|
+
value_int = int(value)
|
50
|
+
result = datetime.fromtimestamp(value_int, tz=UTC)
|
51
|
+
return result.replace(microsecond=int((value - value_int) * 1_000_000))
|
52
|
+
|
53
|
+
|
16
54
|
class LoggingInfo(JobLoggingDBBase):
|
17
55
|
__tablename__ = "LoggingInfo"
|
18
56
|
job_id = Column("JobID", Integer)
|
@@ -21,9 +59,6 @@ class LoggingInfo(JobLoggingDBBase):
|
|
21
59
|
minor_status = Column("MinorStatus", String(128), default="")
|
22
60
|
application_status = Column("ApplicationStatus", String(255), default="")
|
23
61
|
status_time = DateNowColumn("StatusTime")
|
24
|
-
|
25
|
-
status_time_order = Column(
|
26
|
-
"StatusTimeOrder", Numeric(precision=12, scale=3), default=0
|
27
|
-
)
|
62
|
+
status_time_order = Column("StatusTimeOrder", MagicEpochDateTime, default=0)
|
28
63
|
source = Column("StatusSource", String(32), default="Unknown")
|
29
64
|
__table_args__ = (PrimaryKeyConstraint("JobID", "SeqNum"),)
|
@@ -16,8 +16,8 @@ diracx/db/sql/job/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
16
16
|
diracx/db/sql/job/db.py,sha256=PTivVrSl4hrOTgy77WECunPJUJiYzGhSlqO0wYwEuE8,11909
|
17
17
|
diracx/db/sql/job/schema.py,sha256=eFgZshe6NEzOM2qI0HI9Y3abrqDMoQIwa9L0vZugHcU,5431
|
18
18
|
diracx/db/sql/job_logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
-
diracx/db/sql/job_logging/db.py,sha256=
|
20
|
-
diracx/db/sql/job_logging/schema.py,sha256=
|
19
|
+
diracx/db/sql/job_logging/db.py,sha256=BYzlPuvdvHR7wdzQEVWMH_V5kL0bLBZtQkcugnSGbjs,5497
|
20
|
+
diracx/db/sql/job_logging/schema.py,sha256=W2VeE7czBXF6uP2hmjBDur90S4BlidzFXX2V_WZkfzU,2525
|
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
|
@@ -31,8 +31,8 @@ diracx/db/sql/utils/__init__.py,sha256=QkvpqBuIAgkAOywAssYzdxSzUQVZlSUumK7mPxotX
|
|
31
31
|
diracx/db/sql/utils/base.py,sha256=7UxHBNLOSjdrIdslMKW4C_c5H9-6Y1BEimxscri2poE,12367
|
32
32
|
diracx/db/sql/utils/functions.py,sha256=iLqlUIQ6SrDUtDEnZ5szaFbdcINJW15KNbCdGXss6kc,3055
|
33
33
|
diracx/db/sql/utils/types.py,sha256=yU-tXsu6hFGPsr9ba1n3ZjGPnHQI_06lbpkTeDCWJtg,1287
|
34
|
-
diracx_db-0.0.
|
35
|
-
diracx_db-0.0.
|
36
|
-
diracx_db-0.0.
|
37
|
-
diracx_db-0.0.
|
38
|
-
diracx_db-0.0.
|
34
|
+
diracx_db-0.0.1a41.dist-info/METADATA,sha256=pxDO9aAH41RLsym_fs8ySzjZlXjY53GGQwb0MvnE-Lk,644
|
35
|
+
diracx_db-0.0.1a41.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
36
|
+
diracx_db-0.0.1a41.dist-info/entry_points.txt,sha256=UPqhLvb9gui0kOyWeI_edtefcrHToZmQt1p76vIwujo,317
|
37
|
+
diracx_db-0.0.1a41.dist-info/top_level.txt,sha256=vJx10tdRlBX3rF2Psgk5jlwVGZNcL3m_7iQWwgPXt-U,7
|
38
|
+
diracx_db-0.0.1a41.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|