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
@@ -1,168 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
from functools import cached_property
|
3
|
-
from typing import Any, Dict, Optional
|
4
|
-
|
5
|
-
from runnable import context, defaults, exceptions
|
6
|
-
from runnable.datastore import RunLog
|
7
|
-
from runnable.defaults import TypeMapVariable
|
8
|
-
from runnable.extensions.executor import GenericExecutor
|
9
|
-
from runnable.extensions.nodes import TaskNode
|
10
|
-
from runnable.nodes import BaseNode
|
11
|
-
|
12
|
-
logger = logging.getLogger(defaults.LOGGER_NAME)
|
13
|
-
|
14
|
-
|
15
|
-
class RetryExecutor(GenericExecutor):
|
16
|
-
"""
|
17
|
-
The skeleton of an executor class.
|
18
|
-
Any implementation of an executor should inherit this class and over-ride accordingly.
|
19
|
-
|
20
|
-
This is a loaded base class which has a lot of methods already implemented for "typical" executions.
|
21
|
-
Look at the function docs to understand how to use them appropriately.
|
22
|
-
|
23
|
-
For any implementation:
|
24
|
-
1). Who/when should the run log be set up?
|
25
|
-
2). Who/When should the step log be set up?
|
26
|
-
|
27
|
-
"""
|
28
|
-
|
29
|
-
service_name: str = "retry"
|
30
|
-
service_type: str = "executor"
|
31
|
-
run_id: str
|
32
|
-
|
33
|
-
_local: bool = True
|
34
|
-
_original_run_log: Optional[RunLog] = None
|
35
|
-
_restart_initiated: bool = False
|
36
|
-
|
37
|
-
@property
|
38
|
-
def _context(self):
|
39
|
-
return context.run_context
|
40
|
-
|
41
|
-
@cached_property
|
42
|
-
def original_run_log(self):
|
43
|
-
return self._context.run_log_store.get_run_log_by_id(
|
44
|
-
run_id=self.run_id,
|
45
|
-
full=True,
|
46
|
-
)
|
47
|
-
|
48
|
-
def _set_up_for_re_run(self, params: Dict[str, Any]) -> None:
|
49
|
-
# Sync the previous run log catalog to this one.
|
50
|
-
self._context.catalog_handler.sync_between_runs(previous_run_id=self.run_id, run_id=self._context.run_id)
|
51
|
-
|
52
|
-
params.update(self.original_run_log.parameters)
|
53
|
-
|
54
|
-
def _set_up_run_log(self, exists_ok=False):
|
55
|
-
"""
|
56
|
-
Create a run log and put that in the run log store
|
57
|
-
|
58
|
-
If exists_ok, we allow the run log to be already present in the run log store.
|
59
|
-
"""
|
60
|
-
super()._set_up_run_log(exists_ok=exists_ok)
|
61
|
-
|
62
|
-
# Should the parameters be copied from previous execution
|
63
|
-
# self._set_up_for_re_run(params=params)
|
64
|
-
|
65
|
-
def execute_from_graph(self, node: BaseNode, map_variable: TypeMapVariable = None, **kwargs):
|
66
|
-
"""
|
67
|
-
This is the entry point to from the graph execution.
|
68
|
-
|
69
|
-
While the self.execute_graph is responsible for traversing the graph, this function is responsible for
|
70
|
-
actual execution of the node.
|
71
|
-
|
72
|
-
If the node type is:
|
73
|
-
* task : We can delegate to _execute_node after checking the eligibility for re-run in cases of a re-run
|
74
|
-
* success: We can delegate to _execute_node
|
75
|
-
* fail: We can delegate to _execute_node
|
76
|
-
|
77
|
-
For nodes that are internally graphs:
|
78
|
-
* parallel: Delegate the responsibility of execution to the node.execute_as_graph()
|
79
|
-
* dag: Delegate the responsibility of execution to the node.execute_as_graph()
|
80
|
-
* map: Delegate the responsibility of execution to the node.execute_as_graph()
|
81
|
-
|
82
|
-
Transpilers will NEVER use this method and will NEVER call ths method.
|
83
|
-
This method should only be used by interactive executors.
|
84
|
-
|
85
|
-
Args:
|
86
|
-
node (Node): The node to execute
|
87
|
-
map_variable (dict, optional): If the node if of a map state, this corresponds to the value of iterable.
|
88
|
-
Defaults to None.
|
89
|
-
"""
|
90
|
-
step_log = self._context.run_log_store.create_step_log(node.name, node._get_step_log_name(map_variable))
|
91
|
-
|
92
|
-
self.add_code_identities(node=node, step_log=step_log)
|
93
|
-
|
94
|
-
step_log.step_type = node.node_type
|
95
|
-
step_log.status = defaults.PROCESSING
|
96
|
-
|
97
|
-
# Add the step log to the database as per the situation.
|
98
|
-
# If its a terminal node, complete it now
|
99
|
-
if node.node_type in ["success", "fail"]:
|
100
|
-
self._context.run_log_store.add_step_log(step_log, self._context.run_id)
|
101
|
-
self._execute_node(node, map_variable=map_variable, **kwargs)
|
102
|
-
return
|
103
|
-
|
104
|
-
# In retry step
|
105
|
-
if not self._is_step_eligible_for_rerun(node, map_variable=map_variable):
|
106
|
-
# If the node name does not match, we move on to the next node.
|
107
|
-
# If previous run was successful, move on to the next step
|
108
|
-
step_log.mock = True
|
109
|
-
step_log.status = defaults.SUCCESS
|
110
|
-
self._context.run_log_store.add_step_log(step_log, self._context.run_id)
|
111
|
-
return
|
112
|
-
|
113
|
-
# We call an internal function to iterate the sub graphs and execute them
|
114
|
-
if node.is_composite:
|
115
|
-
self._context.run_log_store.add_step_log(step_log, self._context.run_id)
|
116
|
-
node.execute_as_graph(map_variable=map_variable, **kwargs)
|
117
|
-
return
|
118
|
-
|
119
|
-
# Executor specific way to trigger a job
|
120
|
-
self._context.run_log_store.add_step_log(step_log, self._context.run_id)
|
121
|
-
self.execute_node(node=node, map_variable=map_variable, **kwargs)
|
122
|
-
|
123
|
-
def _is_step_eligible_for_rerun(self, node: BaseNode, map_variable: TypeMapVariable = None):
|
124
|
-
"""
|
125
|
-
In case of a re-run, this method checks to see if the previous run step status to determine if a re-run is
|
126
|
-
necessary.
|
127
|
-
* True: If its not a re-run.
|
128
|
-
* True: If its a re-run and we failed in the last run or the corresponding logs do not exist.
|
129
|
-
* False: If its a re-run and we succeeded in the last run.
|
130
|
-
|
131
|
-
Most cases, this logic need not be touched
|
132
|
-
|
133
|
-
Args:
|
134
|
-
node (Node): The node to check against re-run
|
135
|
-
map_variable (dict, optional): If the node if of a map state, this corresponds to the value of iterable..
|
136
|
-
Defaults to None.
|
137
|
-
|
138
|
-
Returns:
|
139
|
-
bool: Eligibility for re-run. True means re-run, False means skip to the next step.
|
140
|
-
"""
|
141
|
-
|
142
|
-
node_step_log_name = node._get_step_log_name(map_variable=map_variable)
|
143
|
-
logger.info(f"Scanning previous run logs for node logs of: {node_step_log_name}")
|
144
|
-
|
145
|
-
if self._restart_initiated:
|
146
|
-
return True
|
147
|
-
|
148
|
-
try:
|
149
|
-
previous_attempt_log, _ = self.original_run_log.search_step_by_internal_name(node_step_log_name)
|
150
|
-
except exceptions.StepLogNotFoundError:
|
151
|
-
logger.warning(f"Did not find the node {node.name} in previous run log")
|
152
|
-
self._restart_initiated = True
|
153
|
-
return True # We should re-run the node.
|
154
|
-
|
155
|
-
logger.info(f"The original step status: {previous_attempt_log.status}")
|
156
|
-
|
157
|
-
if previous_attempt_log.status == defaults.SUCCESS:
|
158
|
-
return False # We need not run the node
|
159
|
-
|
160
|
-
logger.info(f"The new execution should start executing graph from this node {node.name}")
|
161
|
-
self._restart_initiated = True
|
162
|
-
return True
|
163
|
-
|
164
|
-
def execute_node(self, node: BaseNode, map_variable: TypeMapVariable = None, **kwargs):
|
165
|
-
self._execute_node(node, map_variable=map_variable, **kwargs)
|
166
|
-
|
167
|
-
def execute_job(self, node: TaskNode):
|
168
|
-
pass
|