runnable 0.13.0__py3-none-any.whl → 0.16.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- runnable/__init__.py +1 -12
- runnable/catalog.py +29 -5
- runnable/cli.py +268 -215
- runnable/context.py +10 -3
- runnable/datastore.py +212 -53
- runnable/defaults.py +13 -55
- runnable/entrypoints.py +270 -183
- runnable/exceptions.py +28 -2
- runnable/executor.py +133 -86
- runnable/graph.py +37 -13
- runnable/nodes.py +50 -22
- runnable/parameters.py +27 -8
- runnable/pickler.py +1 -1
- runnable/sdk.py +230 -66
- runnable/secrets.py +3 -1
- runnable/tasks.py +99 -41
- runnable/utils.py +59 -39
- {runnable-0.13.0.dist-info → runnable-0.16.0.dist-info}/METADATA +28 -31
- runnable-0.16.0.dist-info/RECORD +23 -0
- {runnable-0.13.0.dist-info → runnable-0.16.0.dist-info}/WHEEL +1 -1
- runnable-0.16.0.dist-info/entry_points.txt +45 -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.py +0 -69
- 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 -870
- 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/integration.py +0 -192
- runnable-0.13.0.dist-info/RECORD +0 -63
- runnable-0.13.0.dist-info/entry_points.txt +0 -41
- {runnable-0.13.0.dist-info → runnable-0.16.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)
|