|
16 | 16 | """Workflow status constants."""
|
17 | 17 |
|
18 | 18 | from enum import Enum
|
19 |
| -from typing import Tuple, TYPE_CHECKING |
| 19 | +from typing import TYPE_CHECKING, Optional, Union |
20 | 20 |
|
| 21 | +from cylc.flow.cycling.loader import get_point |
| 22 | +from cylc.flow.id import tokenise |
21 | 23 | from cylc.flow.wallclock import get_time_string_from_unix_time as time2str
|
22 | 24 |
|
23 | 25 | if TYPE_CHECKING:
|
24 | 26 | from optparse import Values
|
| 27 | + |
| 28 | + from cylc.flow.cycling import PointBase |
25 | 29 | from cylc.flow.scheduler import Scheduler
|
| 30 | + from cylc.flow.task_pool import TaskPool |
26 | 31 |
|
27 | 32 | # Keys for identify API call
|
28 | 33 | KEY_GROUP = "group"
|
@@ -143,62 +148,60 @@ class AutoRestartMode(Enum):
|
143 | 148 | """Workflow will stop immediately but *not* attempt to restart."""
|
144 | 149 |
|
145 | 150 |
|
146 |
| -def get_workflow_status(schd: 'Scheduler') -> Tuple[str, str]: |
147 |
| - """Return the status of the provided workflow. |
148 |
| -
|
149 |
| - This should be a short, concise description of the workflow state. |
150 |
| -
|
151 |
| - Args: |
152 |
| - schd: The running workflow |
153 |
| -
|
154 |
| - Returns: |
155 |
| - tuple - (state, state_msg) |
156 |
| -
|
157 |
| - state: |
158 |
| - The WorkflowState. |
159 |
| - state_msg: |
160 |
| - Text describing the current state (may be an empty string). |
| 151 | +def get_workflow_status(schd: 'Scheduler') -> WorkflowStatus: |
| 152 | + """Return the status of the provided workflow.""" |
| 153 | + if schd.stop_mode is not None: |
| 154 | + return WorkflowStatus.STOPPING |
| 155 | + if schd.is_paused or schd.reload_pending: |
| 156 | + return WorkflowStatus.PAUSED |
| 157 | + return WorkflowStatus.RUNNING |
161 | 158 |
|
162 |
| - """ |
163 |
| - status = WorkflowStatus.RUNNING |
164 |
| - status_msg = '' |
165 | 159 |
|
| 160 | +def get_workflow_status_msg(schd: 'Scheduler') -> str: |
| 161 | + """Return a short, concise status message for the provided workflow.""" |
166 | 162 | if schd.stop_mode is not None:
|
167 |
| - status = WorkflowStatus.STOPPING |
168 |
| - status_msg = f'stopping: {schd.stop_mode.explain()}' |
169 |
| - elif schd.reload_pending: |
170 |
| - status = WorkflowStatus.PAUSED |
171 |
| - status_msg = f'reloading: {schd.reload_pending}' |
172 |
| - elif schd.is_stalled: |
173 |
| - status_msg = 'stalled' |
174 |
| - elif schd.is_paused: |
175 |
| - status = WorkflowStatus.PAUSED |
176 |
| - status_msg = 'paused' |
177 |
| - elif schd.pool.hold_point: |
178 |
| - status_msg = ( |
179 |
| - WORKFLOW_STATUS_RUNNING_TO_HOLD % |
180 |
| - schd.pool.hold_point) |
181 |
| - elif schd.pool.stop_point: |
182 |
| - status_msg = ( |
183 |
| - WORKFLOW_STATUS_RUNNING_TO_STOP % |
184 |
| - schd.pool.stop_point) |
185 |
| - elif schd.stop_clock_time is not None: |
186 |
| - status_msg = ( |
187 |
| - WORKFLOW_STATUS_RUNNING_TO_STOP % |
188 |
| - time2str(schd.stop_clock_time)) |
189 |
| - elif schd.pool.stop_task_id: |
190 |
| - status_msg = ( |
191 |
| - WORKFLOW_STATUS_RUNNING_TO_STOP % |
192 |
| - schd.pool.stop_task_id) |
193 |
| - elif schd.config and schd.config.final_point: |
194 |
| - status_msg = ( |
195 |
| - WORKFLOW_STATUS_RUNNING_TO_STOP % |
196 |
| - schd.config.final_point) |
197 |
| - else: |
198 |
| - # fallback - running indefinitely |
199 |
| - status_msg = 'running' |
200 |
| - |
201 |
| - return (status.value, status_msg) |
| 163 | + return f'stopping: {schd.stop_mode.explain()}' |
| 164 | + if schd.reload_pending: |
| 165 | + return f'reloading: {schd.reload_pending}' |
| 166 | + if schd.is_stalled: |
| 167 | + if schd.is_paused: |
| 168 | + return 'stalled and paused' |
| 169 | + return 'stalled' |
| 170 | + if schd.is_paused: |
| 171 | + return 'paused' |
| 172 | + if schd.stop_clock_time is not None: |
| 173 | + return WORKFLOW_STATUS_RUNNING_TO_STOP % time2str( |
| 174 | + schd.stop_clock_time |
| 175 | + ) |
| 176 | + stop_point_msg = _get_earliest_stop_point_status_msg(schd.pool) |
| 177 | + if stop_point_msg is not None: |
| 178 | + return stop_point_msg |
| 179 | + if schd.config and schd.config.final_point: |
| 180 | + return WORKFLOW_STATUS_RUNNING_TO_STOP % schd.config.final_point |
| 181 | + # fallback - running indefinitely |
| 182 | + return 'running' |
| 183 | + |
| 184 | + |
| 185 | +def _get_earliest_stop_point_status_msg(pool: 'TaskPool') -> Optional[str]: |
| 186 | + """Return the status message for the earliest stop point in the pool, |
| 187 | + if any.""" |
| 188 | + template = WORKFLOW_STATUS_RUNNING_TO_STOP |
| 189 | + prop: Union[PointBase, str, None] = pool.stop_task_id |
| 190 | + min_point: Optional[PointBase] = get_point( |
| 191 | + tokenise(pool.stop_task_id, relative=True)['cycle'] |
| 192 | + if pool.stop_task_id else None |
| 193 | + ) |
| 194 | + for point, tmpl in ( |
| 195 | + (pool.stop_point, WORKFLOW_STATUS_RUNNING_TO_STOP), |
| 196 | + (pool.hold_point, WORKFLOW_STATUS_RUNNING_TO_HOLD) |
| 197 | + ): |
| 198 | + if point is not None and (min_point is None or point < min_point): |
| 199 | + template = tmpl |
| 200 | + min_point = point |
| 201 | + prop = point |
| 202 | + if prop is None: |
| 203 | + return None |
| 204 | + return template % prop |
202 | 205 |
|
203 | 206 |
|
204 | 207 | class RunMode:
|
|
0 commit comments