runnable 0.12.3__py3-none-any.whl → 0.14.0__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.
- runnable/__init__.py +0 -11
- runnable/catalog.py +27 -5
- runnable/cli.py +122 -26
- runnable/datastore.py +71 -35
- runnable/defaults.py +0 -1
- runnable/entrypoints.py +107 -32
- runnable/exceptions.py +6 -2
- runnable/executor.py +28 -9
- runnable/graph.py +37 -12
- runnable/integration.py +7 -2
- runnable/nodes.py +15 -17
- runnable/parameters.py +27 -8
- runnable/pickler.py +1 -1
- runnable/sdk.py +101 -33
- runnable/secrets.py +3 -1
- runnable/tasks.py +246 -34
- runnable/utils.py +41 -13
- {runnable-0.12.3.dist-info → runnable-0.14.0.dist-info}/METADATA +25 -31
- runnable-0.14.0.dist-info/RECORD +24 -0
- {runnable-0.12.3.dist-info → runnable-0.14.0.dist-info}/WHEEL +1 -1
- runnable-0.14.0.dist-info/entry_points.txt +40 -0
- runnable/extensions/__init__.py +0 -0
- runnable/extensions/catalog/__init__.py +0 -21
- runnable/extensions/catalog/file_system/__init__.py +0 -0
- runnable/extensions/catalog/file_system/implementation.py +0 -234
- runnable/extensions/catalog/k8s_pvc/__init__.py +0 -0
- runnable/extensions/catalog/k8s_pvc/implementation.py +0 -16
- runnable/extensions/catalog/k8s_pvc/integration.py +0 -59
- runnable/extensions/executor/__init__.py +0 -649
- runnable/extensions/executor/argo/__init__.py +0 -0
- runnable/extensions/executor/argo/implementation.py +0 -1194
- runnable/extensions/executor/argo/specification.yaml +0 -51
- runnable/extensions/executor/k8s_job/__init__.py +0 -0
- runnable/extensions/executor/k8s_job/implementation_FF.py +0 -259
- runnable/extensions/executor/k8s_job/integration_FF.py +0 -69
- runnable/extensions/executor/local/__init__.py +0 -0
- runnable/extensions/executor/local/implementation.py +0 -71
- runnable/extensions/executor/local_container/__init__.py +0 -0
- runnable/extensions/executor/local_container/implementation.py +0 -446
- runnable/extensions/executor/mocked/__init__.py +0 -0
- runnable/extensions/executor/mocked/implementation.py +0 -154
- runnable/extensions/executor/retry/__init__.py +0 -0
- runnable/extensions/executor/retry/implementation.py +0 -168
- runnable/extensions/nodes.py +0 -855
- runnable/extensions/run_log_store/__init__.py +0 -0
- runnable/extensions/run_log_store/chunked_file_system/__init__.py +0 -0
- runnable/extensions/run_log_store/chunked_file_system/implementation.py +0 -111
- runnable/extensions/run_log_store/chunked_k8s_pvc/__init__.py +0 -0
- runnable/extensions/run_log_store/chunked_k8s_pvc/implementation.py +0 -21
- runnable/extensions/run_log_store/chunked_k8s_pvc/integration.py +0 -61
- runnable/extensions/run_log_store/db/implementation_FF.py +0 -157
- runnable/extensions/run_log_store/db/integration_FF.py +0 -0
- runnable/extensions/run_log_store/file_system/__init__.py +0 -0
- runnable/extensions/run_log_store/file_system/implementation.py +0 -140
- runnable/extensions/run_log_store/generic_chunked.py +0 -557
- runnable/extensions/run_log_store/k8s_pvc/__init__.py +0 -0
- runnable/extensions/run_log_store/k8s_pvc/implementation.py +0 -21
- runnable/extensions/run_log_store/k8s_pvc/integration.py +0 -56
- runnable/extensions/secrets/__init__.py +0 -0
- runnable/extensions/secrets/dotenv/__init__.py +0 -0
- runnable/extensions/secrets/dotenv/implementation.py +0 -100
- runnable-0.12.3.dist-info/RECORD +0 -64
- runnable-0.12.3.dist-info/entry_points.txt +0 -41
- {runnable-0.12.3.dist-info → runnable-0.14.0.dist-info/licenses}/LICENSE +0 -0
File without changes
|
File without changes
|
@@ -1,111 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import logging
|
3
|
-
from pathlib import Path
|
4
|
-
from string import Template
|
5
|
-
from typing import Any, Dict, Optional, Sequence, Union
|
6
|
-
|
7
|
-
from runnable import defaults, utils
|
8
|
-
from runnable.extensions.run_log_store.generic_chunked import ChunkedRunLogStore
|
9
|
-
|
10
|
-
logger = logging.getLogger(defaults.LOGGER_NAME)
|
11
|
-
|
12
|
-
T = Union[str, Path]
|
13
|
-
|
14
|
-
|
15
|
-
class ChunkedFileSystemRunLogStore(ChunkedRunLogStore):
|
16
|
-
"""
|
17
|
-
File system run log store but chunks the run log into thread safe chunks.
|
18
|
-
This enables executions to be parallel.
|
19
|
-
"""
|
20
|
-
|
21
|
-
service_name: str = "chunked-fs"
|
22
|
-
log_folder: str = defaults.LOG_LOCATION_FOLDER
|
23
|
-
|
24
|
-
def get_summary(self) -> Dict[str, Any]:
|
25
|
-
summary = {"Type": self.service_name, "Location": self.log_folder}
|
26
|
-
|
27
|
-
return summary
|
28
|
-
|
29
|
-
def get_matches(self, run_id: str, name: str, multiple_allowed: bool = False) -> Optional[Union[Sequence[T], T]]:
|
30
|
-
"""
|
31
|
-
Get contents of files matching the pattern name*
|
32
|
-
|
33
|
-
Args:
|
34
|
-
run_id (str): The run id
|
35
|
-
name (str): The suffix of the file name to check in the run log store.
|
36
|
-
"""
|
37
|
-
log_folder = self.log_folder_with_run_id(run_id=run_id)
|
38
|
-
sub_name = Template(name).safe_substitute({"creation_time": ""})
|
39
|
-
|
40
|
-
matches = list(log_folder.glob(f"{sub_name}*"))
|
41
|
-
|
42
|
-
if matches:
|
43
|
-
if not multiple_allowed:
|
44
|
-
if len(matches) > 1:
|
45
|
-
msg = f"Multiple matches found for {name} while multiple is not allowed"
|
46
|
-
raise Exception(msg)
|
47
|
-
return matches[0]
|
48
|
-
return matches
|
49
|
-
|
50
|
-
return None
|
51
|
-
|
52
|
-
def log_folder_with_run_id(self, run_id: str) -> Path:
|
53
|
-
"""
|
54
|
-
Utility function to get the log folder for a run id.
|
55
|
-
|
56
|
-
Args:
|
57
|
-
run_id (str): The run id
|
58
|
-
|
59
|
-
Returns:
|
60
|
-
Path: The path to the log folder with the run id
|
61
|
-
"""
|
62
|
-
return Path(self.log_folder) / run_id
|
63
|
-
|
64
|
-
def safe_suffix_json(self, name: Union[Path, str]) -> str:
|
65
|
-
"""
|
66
|
-
Safely attach a suffix to a json file.
|
67
|
-
|
68
|
-
Args:
|
69
|
-
name (Path): The name of the file with or without suffix of json
|
70
|
-
|
71
|
-
Returns:
|
72
|
-
str : The name of the file with .json
|
73
|
-
"""
|
74
|
-
if str(name).endswith("json"):
|
75
|
-
return str(name)
|
76
|
-
|
77
|
-
return str(name) + ".json"
|
78
|
-
|
79
|
-
def _store(self, run_id: str, contents: dict, name: Union[Path, str], insert=False):
|
80
|
-
"""
|
81
|
-
Store the contents against the name in the folder.
|
82
|
-
|
83
|
-
Args:
|
84
|
-
run_id (str): The run id
|
85
|
-
contents (dict): The dict to store
|
86
|
-
name (str): The name to store as
|
87
|
-
"""
|
88
|
-
if insert:
|
89
|
-
name = self.log_folder_with_run_id(run_id=run_id) / name
|
90
|
-
|
91
|
-
utils.safe_make_dir(self.log_folder_with_run_id(run_id=run_id))
|
92
|
-
|
93
|
-
with open(self.safe_suffix_json(name), "w") as fw:
|
94
|
-
json.dump(contents, fw, ensure_ascii=True, indent=4)
|
95
|
-
|
96
|
-
def _retrieve(self, name: Union[str, Path]) -> dict:
|
97
|
-
"""
|
98
|
-
Does the job of retrieving from the folder.
|
99
|
-
|
100
|
-
Args:
|
101
|
-
name (str): the name of the file to retrieve
|
102
|
-
|
103
|
-
Returns:
|
104
|
-
dict: The contents
|
105
|
-
"""
|
106
|
-
contents: dict = {}
|
107
|
-
|
108
|
-
with open(self.safe_suffix_json(name), "r") as fr:
|
109
|
-
contents = json.load(fr)
|
110
|
-
|
111
|
-
return contents
|
File without changes
|
@@ -1,21 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
from pathlib import Path
|
3
|
-
|
4
|
-
from runnable import defaults
|
5
|
-
from runnable.extensions.run_log_store.chunked_file_system.implementation import ChunkedFileSystemRunLogStore
|
6
|
-
|
7
|
-
logger = logging.getLogger(defaults.NAME)
|
8
|
-
|
9
|
-
|
10
|
-
class ChunkedK8PersistentVolumeRunLogstore(ChunkedFileSystemRunLogStore):
|
11
|
-
"""
|
12
|
-
Uses the K8s Persistent Volumes to store run logs.
|
13
|
-
"""
|
14
|
-
|
15
|
-
service_name: str = "chunked-k8s-pvc"
|
16
|
-
persistent_volume_name: str
|
17
|
-
mount_path: str
|
18
|
-
|
19
|
-
@property
|
20
|
-
def log_folder_name(self) -> str:
|
21
|
-
return str(Path(self.mount_path) / self.log_folder)
|
@@ -1,61 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
from typing import cast
|
3
|
-
|
4
|
-
from runnable import defaults
|
5
|
-
from runnable.integration import BaseIntegration
|
6
|
-
|
7
|
-
logger = logging.getLogger(defaults.NAME)
|
8
|
-
|
9
|
-
|
10
|
-
class LocalCompute(BaseIntegration):
|
11
|
-
"""
|
12
|
-
Integration between local and k8's pvc
|
13
|
-
"""
|
14
|
-
|
15
|
-
executor_type = "local"
|
16
|
-
service_type = "run_log_store" # One of secret, catalog, datastore
|
17
|
-
service_provider = "chunked-k8s-pvc" # The actual implementation of the service
|
18
|
-
|
19
|
-
def validate(self, **kwargs):
|
20
|
-
msg = "We can't use the local compute k8s pvc store integration."
|
21
|
-
raise Exception(msg)
|
22
|
-
|
23
|
-
|
24
|
-
class LocalContainerCompute(BaseIntegration):
|
25
|
-
"""
|
26
|
-
Integration between local-container and k8's pvc
|
27
|
-
"""
|
28
|
-
|
29
|
-
executor_type = "local-container"
|
30
|
-
service_type = "run_log_store" # One of secret, catalog, datastore
|
31
|
-
service_provider = "chunked-k8s-pvc" # The actual implementation of the service
|
32
|
-
|
33
|
-
def validate(self, **kwargs):
|
34
|
-
msg = "We can't use the local-container compute k8s pvc store integration."
|
35
|
-
raise Exception(msg)
|
36
|
-
|
37
|
-
|
38
|
-
class ArgoCompute(BaseIntegration):
|
39
|
-
"""
|
40
|
-
Integration between argo and k8's pvc
|
41
|
-
"""
|
42
|
-
|
43
|
-
executor_type = "argo"
|
44
|
-
service_type = "run_log_store" # One of secret, catalog, datastore
|
45
|
-
service_provider = "chunked-k8s-pvc" # The actual implementation of the service
|
46
|
-
|
47
|
-
def configure_for_traversal(self, **kwargs):
|
48
|
-
from runnable.extensions.executor.argo.implementation import ArgoExecutor, UserVolumeMounts
|
49
|
-
from runnable.extensions.run_log_store.chunked_k8s_pvc.implementation import (
|
50
|
-
ChunkedK8PersistentVolumeRunLogstore,
|
51
|
-
)
|
52
|
-
|
53
|
-
self.executor = cast(ArgoExecutor, self.executor)
|
54
|
-
self.service = cast(ChunkedK8PersistentVolumeRunLogstore, self.service)
|
55
|
-
|
56
|
-
volume_mount = UserVolumeMounts(
|
57
|
-
name=self.service.persistent_volume_name,
|
58
|
-
mount_path=self.service.mount_path,
|
59
|
-
)
|
60
|
-
|
61
|
-
self.executor.persistent_volumes.append(volume_mount)
|
@@ -1,157 +0,0 @@
|
|
1
|
-
import datetime
|
2
|
-
import json
|
3
|
-
import logging
|
4
|
-
from pathlib import Path
|
5
|
-
from string import Template
|
6
|
-
from typing import Any, Dict, List, Optional, Union, cast
|
7
|
-
|
8
|
-
from runnable import defaults, utils
|
9
|
-
from runnable.extensions.run_log_store.generic_chunked import ChunkedRunLogStore
|
10
|
-
|
11
|
-
logger = logging.getLogger(defaults.LOGGER_NAME)
|
12
|
-
|
13
|
-
|
14
|
-
class DBRunLogStore(ChunkedRunLogStore):
|
15
|
-
"""
|
16
|
-
File system run log store but chunks the run log into thread safe chunks.
|
17
|
-
This enables executions to be parallel.
|
18
|
-
"""
|
19
|
-
|
20
|
-
service_name: str = "chunked-fs"
|
21
|
-
connection_string: str
|
22
|
-
db_name: str
|
23
|
-
|
24
|
-
_DB_LOG: Any = None
|
25
|
-
_engine: Any = None
|
26
|
-
_session: Any = None
|
27
|
-
_connection_string: str = ""
|
28
|
-
_base: Any = None
|
29
|
-
|
30
|
-
def model_post_init(self, _: Any) -> None:
|
31
|
-
run_context = self._context
|
32
|
-
|
33
|
-
secrets = cast(Dict[str, str], run_context.secrets_handler.get())
|
34
|
-
connection_string = Template(self.connection_string).safe_substitute(**secrets)
|
35
|
-
|
36
|
-
try:
|
37
|
-
import sqlalchemy
|
38
|
-
from sqlalchemy import Column, DateTime, Integer, Sequence, Text
|
39
|
-
from sqlalchemy.orm import declarative_base, sessionmaker
|
40
|
-
|
41
|
-
Base = declarative_base()
|
42
|
-
|
43
|
-
class DBLog(Base):
|
44
|
-
"""
|
45
|
-
Base table for storing run logs in database.
|
46
|
-
|
47
|
-
In this model, we fragment the run log into logical units that are concurrent safe.
|
48
|
-
"""
|
49
|
-
|
50
|
-
__tablename__ = self.db_name
|
51
|
-
pk = Column(Integer, Sequence("id_seq"), primary_key=True)
|
52
|
-
run_id = Column(Text, index=True)
|
53
|
-
attribute_key = Column(Text) # run_log, step_internal_name, parameter_key etc
|
54
|
-
attribute_type = Column(Text) # RunLog, Step, Branch, Parameter
|
55
|
-
attribute_value = Column(Text) # The JSON string
|
56
|
-
created_at = Column(DateTime, default=datetime.datetime.utcnow)
|
57
|
-
|
58
|
-
self._engine = sqlalchemy.create_engine(connection_string, pool_pre_ping=True)
|
59
|
-
self._session = sessionmaker(bind=self._engine)
|
60
|
-
self._DB_LOG = DBLog
|
61
|
-
self._connection_string = connection_string
|
62
|
-
self._base = Base
|
63
|
-
|
64
|
-
except ImportError as _e:
|
65
|
-
logger.exception("Unable to import SQLalchemy, is it installed?")
|
66
|
-
msg = "SQLAlchemy is required for this extension. Please install it"
|
67
|
-
raise Exception(msg) from _e
|
68
|
-
|
69
|
-
def create_tables(self):
|
70
|
-
import sqlalchemy
|
71
|
-
|
72
|
-
engine = sqlalchemy.create_engine(self._connection_string)
|
73
|
-
self._base.metadata.create_all(engine)
|
74
|
-
|
75
|
-
def get_matches(self, run_id: str, name: str, multiple_allowed: bool = False) -> Optional[Union[List[Path], Path]]:
|
76
|
-
"""
|
77
|
-
Get contents of files matching the pattern name*
|
78
|
-
|
79
|
-
Args:
|
80
|
-
run_id (str): The run id
|
81
|
-
name (str): The suffix of the file name to check in the run log store.
|
82
|
-
"""
|
83
|
-
log_folder = self.log_folder_with_run_id(run_id=run_id)
|
84
|
-
|
85
|
-
sub_name = Template(name).safe_substitute({"creation_time": ""})
|
86
|
-
|
87
|
-
matches = list(log_folder.glob(f"{sub_name}*"))
|
88
|
-
if matches:
|
89
|
-
if not multiple_allowed:
|
90
|
-
if len(matches) > 1:
|
91
|
-
msg = f"Multiple matches found for {name} while multiple is not allowed"
|
92
|
-
raise Exception(msg)
|
93
|
-
return matches[0]
|
94
|
-
return matches
|
95
|
-
|
96
|
-
return None
|
97
|
-
|
98
|
-
def log_folder_with_run_id(self, run_id: str) -> Path:
|
99
|
-
"""
|
100
|
-
Utility function to get the log folder for a run id.
|
101
|
-
|
102
|
-
Args:
|
103
|
-
run_id (str): The run id
|
104
|
-
|
105
|
-
Returns:
|
106
|
-
Path: The path to the log folder with the run id
|
107
|
-
"""
|
108
|
-
return Path(self.log_folder) / run_id
|
109
|
-
|
110
|
-
def safe_suffix_json(self, name: Union[Path, str]) -> str:
|
111
|
-
"""
|
112
|
-
Safely attach a suffix to a json file.
|
113
|
-
|
114
|
-
Args:
|
115
|
-
name (Path): The name of the file with or without suffix of json
|
116
|
-
|
117
|
-
Returns:
|
118
|
-
str : The name of the file with .json
|
119
|
-
"""
|
120
|
-
if str(name).endswith("json"):
|
121
|
-
return str(name)
|
122
|
-
|
123
|
-
return str(name) + ".json"
|
124
|
-
|
125
|
-
def _store(self, run_id: str, contents: dict, name: Union[Path, str], insert=False):
|
126
|
-
"""
|
127
|
-
Store the contents against the name in the folder.
|
128
|
-
|
129
|
-
Args:
|
130
|
-
run_id (str): The run id
|
131
|
-
contents (dict): The dict to store
|
132
|
-
name (str): The name to store as
|
133
|
-
"""
|
134
|
-
if insert:
|
135
|
-
name = self.log_folder_with_run_id(run_id=run_id) / name
|
136
|
-
|
137
|
-
utils.safe_make_dir(self.log_folder_with_run_id(run_id=run_id))
|
138
|
-
|
139
|
-
with open(self.safe_suffix_json(name), "w") as fw:
|
140
|
-
json.dump(contents, fw, ensure_ascii=True, indent=4)
|
141
|
-
|
142
|
-
def _retrieve(self, name: Path) -> dict:
|
143
|
-
"""
|
144
|
-
Does the job of retrieving from the folder.
|
145
|
-
|
146
|
-
Args:
|
147
|
-
name (str): the name of the file to retrieve
|
148
|
-
|
149
|
-
Returns:
|
150
|
-
dict: The contents
|
151
|
-
"""
|
152
|
-
contents: dict = {}
|
153
|
-
|
154
|
-
with open(self.safe_suffix_json(name), "r") as fr:
|
155
|
-
contents = json.load(fr)
|
156
|
-
|
157
|
-
return contents
|
File without changes
|
File without changes
|
@@ -1,140 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import logging
|
3
|
-
from pathlib import Path
|
4
|
-
from typing import Any, Dict
|
5
|
-
|
6
|
-
from runnable import defaults, exceptions, utils
|
7
|
-
from runnable.datastore import BaseRunLogStore, RunLog
|
8
|
-
|
9
|
-
logger = logging.getLogger(defaults.LOGGER_NAME)
|
10
|
-
|
11
|
-
|
12
|
-
class FileSystemRunLogstore(BaseRunLogStore):
|
13
|
-
"""
|
14
|
-
In this type of Run Log store, we use a file system to store the JSON run log.
|
15
|
-
|
16
|
-
Every single run is stored as a different file which makes it compatible across other store types.
|
17
|
-
|
18
|
-
When to use:
|
19
|
-
When locally testing a pipeline and have the need to compare across runs.
|
20
|
-
Its fully featured and perfectly fine if your local environment is where you would do everything.
|
21
|
-
|
22
|
-
Do not use:
|
23
|
-
If you need parallelization on local, this run log would not support it.
|
24
|
-
|
25
|
-
Example config:
|
26
|
-
|
27
|
-
run_log:
|
28
|
-
type: file-system
|
29
|
-
config:
|
30
|
-
log_folder: The folder to out the logs. Defaults to .run_log_store
|
31
|
-
|
32
|
-
"""
|
33
|
-
|
34
|
-
service_name: str = "file-system"
|
35
|
-
log_folder: str = defaults.LOG_LOCATION_FOLDER
|
36
|
-
|
37
|
-
@property
|
38
|
-
def log_folder_name(self):
|
39
|
-
return self.log_folder
|
40
|
-
|
41
|
-
def get_summary(self) -> Dict[str, Any]:
|
42
|
-
summary = {"Type": self.service_name, "Location": self.log_folder}
|
43
|
-
|
44
|
-
return summary
|
45
|
-
|
46
|
-
def write_to_folder(self, run_log: RunLog):
|
47
|
-
"""
|
48
|
-
Write the run log to the folder
|
49
|
-
|
50
|
-
Args:
|
51
|
-
run_log (RunLog): The run log to be added to the database
|
52
|
-
"""
|
53
|
-
write_to = self.log_folder_name
|
54
|
-
utils.safe_make_dir(write_to)
|
55
|
-
|
56
|
-
write_to_path = Path(write_to)
|
57
|
-
run_id = run_log.run_id
|
58
|
-
json_file_path = write_to_path / f"{run_id}.json"
|
59
|
-
|
60
|
-
with json_file_path.open("w") as fw:
|
61
|
-
json.dump(run_log.model_dump(), fw, ensure_ascii=True, indent=4) # pylint: disable=no-member
|
62
|
-
|
63
|
-
def get_from_folder(self, run_id: str) -> RunLog:
|
64
|
-
"""
|
65
|
-
Look into the run log folder for the run log for the run id.
|
66
|
-
|
67
|
-
If the run log does not exist, raise an exception. If it does, decode it
|
68
|
-
as a RunLog and return it
|
69
|
-
|
70
|
-
Args:
|
71
|
-
run_id (str): The requested run id to retrieve the run log store
|
72
|
-
|
73
|
-
Raises:
|
74
|
-
FileNotFoundError: If the Run Log has not been found.
|
75
|
-
|
76
|
-
Returns:
|
77
|
-
RunLog: The decoded Run log
|
78
|
-
"""
|
79
|
-
write_to = self.log_folder_name
|
80
|
-
|
81
|
-
read_from_path = Path(write_to)
|
82
|
-
json_file_path = read_from_path / f"{run_id}.json"
|
83
|
-
|
84
|
-
if not json_file_path.exists():
|
85
|
-
raise FileNotFoundError(f"Expected {json_file_path} is not present")
|
86
|
-
|
87
|
-
with json_file_path.open("r") as fr:
|
88
|
-
json_str = json.load(fr)
|
89
|
-
run_log = RunLog(**json_str) # pylint: disable=no-member
|
90
|
-
return run_log
|
91
|
-
|
92
|
-
def create_run_log(
|
93
|
-
self,
|
94
|
-
run_id: str,
|
95
|
-
dag_hash: str = "",
|
96
|
-
use_cached: bool = False,
|
97
|
-
tag: str = "",
|
98
|
-
original_run_id: str = "",
|
99
|
-
status: str = defaults.CREATED,
|
100
|
-
**kwargs,
|
101
|
-
) -> RunLog:
|
102
|
-
"""
|
103
|
-
# Creates a Run log
|
104
|
-
# Adds it to the db
|
105
|
-
"""
|
106
|
-
|
107
|
-
try:
|
108
|
-
self.get_run_log_by_id(run_id=run_id, full=False)
|
109
|
-
raise exceptions.RunLogExistsError(run_id=run_id)
|
110
|
-
except exceptions.RunLogNotFoundError:
|
111
|
-
pass
|
112
|
-
|
113
|
-
logger.info(f"{self.service_name} Creating a Run Log for : {run_id}")
|
114
|
-
run_log = RunLog(
|
115
|
-
run_id=run_id,
|
116
|
-
dag_hash=dag_hash,
|
117
|
-
tag=tag,
|
118
|
-
status=status,
|
119
|
-
)
|
120
|
-
self.write_to_folder(run_log)
|
121
|
-
return run_log
|
122
|
-
|
123
|
-
def get_run_log_by_id(self, run_id: str, full: bool = False, **kwargs) -> RunLog:
|
124
|
-
"""
|
125
|
-
# Returns the run_log defined by id
|
126
|
-
# Raises Exception if not found
|
127
|
-
"""
|
128
|
-
try:
|
129
|
-
logger.info(f"{self.service_name} Getting a Run Log for : {run_id}")
|
130
|
-
run_log = self.get_from_folder(run_id)
|
131
|
-
return run_log
|
132
|
-
except FileNotFoundError as e:
|
133
|
-
raise exceptions.RunLogNotFoundError(run_id) from e
|
134
|
-
|
135
|
-
def put_run_log(self, run_log: RunLog, **kwargs):
|
136
|
-
"""
|
137
|
-
# Puts the run_log into the database
|
138
|
-
"""
|
139
|
-
logger.info(f"{self.service_name} Putting the run log in the DB: {run_log.run_id}")
|
140
|
-
self.write_to_folder(run_log)
|