meerschaum 2.2.7__py3-none-any.whl → 2.3.0.dev3__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.
- meerschaum/__init__.py +6 -1
- meerschaum/_internal/arguments/_parse_arguments.py +10 -3
- meerschaum/_internal/arguments/_parser.py +44 -15
- meerschaum/_internal/entry.py +22 -1
- meerschaum/_internal/shell/Shell.py +129 -31
- meerschaum/actions/__init__.py +8 -6
- meerschaum/actions/api.py +12 -12
- meerschaum/actions/attach.py +108 -0
- meerschaum/actions/delete.py +35 -26
- meerschaum/actions/show.py +119 -148
- meerschaum/actions/start.py +85 -75
- meerschaum/actions/stop.py +68 -39
- meerschaum/api/_events.py +18 -1
- meerschaum/api/_oauth2.py +2 -0
- meerschaum/api/_websockets.py +2 -2
- meerschaum/api/dash/jobs.py +5 -2
- meerschaum/api/routes/__init__.py +1 -0
- meerschaum/api/routes/_actions.py +122 -44
- meerschaum/api/routes/_jobs.py +371 -0
- meerschaum/api/routes/_pipes.py +5 -5
- meerschaum/config/_default.py +1 -0
- meerschaum/config/_paths.py +1 -0
- meerschaum/config/_shell.py +8 -3
- meerschaum/config/_version.py +1 -1
- meerschaum/config/static/__init__.py +10 -0
- meerschaum/connectors/__init__.py +9 -11
- meerschaum/connectors/api/APIConnector.py +18 -1
- meerschaum/connectors/api/_actions.py +60 -71
- meerschaum/connectors/api/_jobs.py +330 -0
- meerschaum/connectors/parse.py +23 -7
- meerschaum/plugins/__init__.py +89 -5
- meerschaum/utils/daemon/Daemon.py +255 -30
- meerschaum/utils/daemon/FileDescriptorInterceptor.py +5 -5
- meerschaum/utils/daemon/RotatingFile.py +10 -6
- meerschaum/utils/daemon/StdinFile.py +110 -0
- meerschaum/utils/daemon/__init__.py +13 -7
- meerschaum/utils/formatting/__init__.py +2 -1
- meerschaum/utils/formatting/_jobs.py +83 -54
- meerschaum/utils/formatting/_shell.py +6 -0
- meerschaum/utils/jobs/_Job.py +710 -0
- meerschaum/utils/jobs/__init__.py +245 -0
- meerschaum/utils/misc.py +18 -17
- meerschaum/utils/packages/_packages.py +2 -2
- meerschaum/utils/prompt.py +16 -8
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dev3.dist-info}/METADATA +9 -9
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dev3.dist-info}/RECORD +52 -46
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dev3.dist-info}/WHEEL +1 -1
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dev3.dist-info}/LICENSE +0 -0
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dev3.dist-info}/NOTICE +0 -0
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dev3.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dev3.dist-info}/top_level.txt +0 -0
- {meerschaum-2.2.7.dist-info → meerschaum-2.3.0.dev3.dist-info}/zip-safe +0 -0
meerschaum/actions/start.py
CHANGED
@@ -78,6 +78,9 @@ def _start_api(action: Optional[List[str]] = None, **kw):
|
|
78
78
|
def _start_jobs(
|
79
79
|
action: Optional[List[str]] = None,
|
80
80
|
name: Optional[str] = None,
|
81
|
+
sysargs: Optional[List[str]] = None,
|
82
|
+
executor_keys: Optional[str] = None,
|
83
|
+
debug: bool = False,
|
81
84
|
**kw
|
82
85
|
) -> SuccessTuple:
|
83
86
|
"""
|
@@ -111,11 +114,16 @@ def _start_jobs(
|
|
111
114
|
"""
|
112
115
|
import textwrap
|
113
116
|
from meerschaum.utils.warnings import warn, info
|
114
|
-
from meerschaum.utils.daemon import (
|
115
|
-
daemon_action, Daemon, get_daemon_ids, get_daemons, get_filtered_daemons,
|
116
|
-
get_stopped_daemons, get_running_daemons, get_paused_daemons,
|
117
|
-
)
|
118
117
|
from meerschaum.utils.daemon._names import get_new_daemon_name
|
118
|
+
from meerschaum.utils.jobs import (
|
119
|
+
Job,
|
120
|
+
get_jobs,
|
121
|
+
get_filtered_jobs,
|
122
|
+
get_stopped_jobs,
|
123
|
+
get_running_jobs,
|
124
|
+
get_paused_jobs,
|
125
|
+
get_restart_jobs,
|
126
|
+
)
|
119
127
|
from meerschaum._internal.arguments._parse_arguments import parse_arguments
|
120
128
|
from meerschaum.actions import actions
|
121
129
|
from meerschaum.utils.prompt import yes_no
|
@@ -125,7 +133,7 @@ def _start_jobs(
|
|
125
133
|
from meerschaum.utils.misc import items_str
|
126
134
|
|
127
135
|
names = []
|
128
|
-
|
136
|
+
jobs = get_filtered_jobs(executor_keys, debug=debug)
|
129
137
|
|
130
138
|
new_job = len(list(action)) > 0
|
131
139
|
_potential_jobs = {'known': [], 'unknown': []}
|
@@ -134,7 +142,7 @@ def _start_jobs(
|
|
134
142
|
for a in action:
|
135
143
|
_potential_jobs[(
|
136
144
|
'known'
|
137
|
-
if a in
|
145
|
+
if a in jobs
|
138
146
|
else 'unknown'
|
139
147
|
)].append(a)
|
140
148
|
|
@@ -182,88 +190,83 @@ def _start_jobs(
|
|
182
190
|
|
183
191
|
### No action or --name was provided. Ask to start all stopped jobs.
|
184
192
|
else:
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
193
|
+
running_jobs = get_running_jobs(executor_keys, jobs, debug=debug)
|
194
|
+
paused_jobs = get_paused_jobs(executor_keys, jobs, debug=debug)
|
195
|
+
stopped_jobs = get_stopped_jobs(executor_keys, jobs, debug=debug)
|
196
|
+
|
197
|
+
if not stopped_jobs and not paused_jobs:
|
198
|
+
if not running_jobs:
|
199
|
+
return False, "No jobs to start"
|
191
200
|
return True, "All jobs are running."
|
192
201
|
|
193
|
-
names = [
|
202
|
+
names = [
|
203
|
+
name
|
204
|
+
for name in list(stopped_jobs) + list(paused_jobs)
|
205
|
+
]
|
194
206
|
|
195
207
|
def _run_new_job(name: Optional[str] = None):
|
196
|
-
kw['action'] = action
|
197
208
|
name = name or get_new_daemon_name()
|
198
|
-
|
199
|
-
|
200
|
-
return _action_success_tuple, name
|
201
|
-
|
202
|
-
def _run_existing_job(name: Optional[str] = None):
|
203
|
-
daemon = Daemon(daemon_id=name)
|
204
|
-
if daemon.process is not None:
|
205
|
-
if daemon.status == 'paused':
|
206
|
-
return daemon.resume(), daemon.daemon_id
|
207
|
-
return (True, f"Job '{name}' is already running."), daemon.daemon_id
|
208
|
-
|
209
|
-
if not daemon.path.exists():
|
210
|
-
if not kw.get('nopretty', False):
|
211
|
-
warn(f"There isn't a job with the name '{name}'.", stack=False)
|
212
|
-
print(
|
213
|
-
f"You can start a new job named '{name}' with `start job "
|
214
|
-
+ "{options}" + f" --name {name}`"
|
215
|
-
)
|
216
|
-
return (False, f"Job '{name}' does not exist."), daemon.daemon_id
|
209
|
+
job = Job(name, sysargs, executor_keys=executor_keys)
|
210
|
+
return job.start(debug=debug), name
|
217
211
|
|
218
|
-
|
212
|
+
def _run_existing_job(name: str):
|
213
|
+
job = Job(name, executor_keys=executor_keys)
|
214
|
+
return job.start(debug=debug), name
|
219
215
|
|
220
216
|
if not names:
|
221
217
|
return False, "No jobs to start."
|
222
218
|
|
223
219
|
### Get user permission to clear logs.
|
224
|
-
|
225
|
-
if not kw.get('force', False) and
|
226
|
-
|
227
|
-
|
228
|
-
if
|
229
|
-
pprint_jobs(
|
220
|
+
_filtered_jobs = get_filtered_jobs(executor_keys, names, debug=debug)
|
221
|
+
if not kw.get('force', False) and _filtered_jobs:
|
222
|
+
_filtered_running_jobs = get_running_jobs(executor_keys, _filtered_jobs, debug=debug)
|
223
|
+
_skipped_jobs = []
|
224
|
+
if _filtered_running_jobs:
|
225
|
+
pprint_jobs(_filtered_running_jobs)
|
230
226
|
if yes_no(
|
231
227
|
"Do you want to first stop these jobs?",
|
232
|
-
default
|
233
|
-
yes
|
234
|
-
noask
|
228
|
+
default='n',
|
229
|
+
yes=kw.get('yes', False),
|
230
|
+
noask=kw.get('noask', False)
|
235
231
|
):
|
236
232
|
stop_success_tuple = actions['stop'](
|
237
|
-
action
|
238
|
-
force
|
233
|
+
action=['jobs'] + [_name for _name in _filtered_running_jobs],
|
234
|
+
force=True,
|
235
|
+
executor_keys=executor_keys,
|
236
|
+
debug=debug,
|
239
237
|
)
|
240
238
|
if not stop_success_tuple[0]:
|
241
239
|
warn(
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
240
|
+
(
|
241
|
+
"Failed to stop job"
|
242
|
+
+ ("s" if len(_filtered_running_jobs) != 1 else '')
|
243
|
+
+ items_str([_name for _name in _filtered_running_jobs])
|
244
|
+
+ "."
|
245
|
+
),
|
246
|
+
stack=False
|
246
247
|
)
|
247
|
-
for
|
248
|
-
names.remove(
|
249
|
-
|
248
|
+
for _name in _filtered_running_jobs:
|
249
|
+
names.remove(_name)
|
250
|
+
_filtered_jobs.pop(_name)
|
250
251
|
else:
|
251
252
|
info(
|
252
253
|
"Skipping already running job"
|
253
|
-
+ ("s" if len(
|
254
|
-
+
|
254
|
+
+ ("s" if len(_filtered_running_jobs) != 1 else '')
|
255
|
+
+ ' '
|
256
|
+
+ items_str([_name for _name in _filtered_running_jobs])
|
257
|
+
+ '.'
|
255
258
|
)
|
256
|
-
for
|
257
|
-
names.remove(
|
258
|
-
|
259
|
-
|
259
|
+
for _name in _filtered_running_jobs:
|
260
|
+
names.remove(_name)
|
261
|
+
_filtered_jobs.pop(_name)
|
262
|
+
_skipped_jobs.append(_name)
|
260
263
|
|
261
|
-
if not
|
262
|
-
return len(
|
264
|
+
if not _filtered_jobs:
|
265
|
+
return len(_skipped_jobs) > 0, "No jobs to start."
|
263
266
|
|
264
|
-
pprint_jobs(
|
267
|
+
pprint_jobs(_filtered_jobs, nopretty=kw.get('nopretty', False))
|
265
268
|
info(
|
266
|
-
|
269
|
+
"Starting the job"
|
267
270
|
+ ("s" if len(names) != 1 else "")
|
268
271
|
+ " " + items_str(names)
|
269
272
|
+ "..."
|
@@ -278,7 +281,11 @@ def _start_jobs(
|
|
278
281
|
)
|
279
282
|
if not kw.get('nopretty', False):
|
280
283
|
print_tuple(success_tuple)
|
281
|
-
|
284
|
+
|
285
|
+
if success_tuple[0]:
|
286
|
+
_successes.append(_name)
|
287
|
+
else:
|
288
|
+
_failures.append(_name)
|
282
289
|
|
283
290
|
msg = (
|
284
291
|
(("Successfully started job" + ("s" if len(_successes) != 1 else '')
|
@@ -289,25 +296,28 @@ def _start_jobs(
|
|
289
296
|
)
|
290
297
|
return len(_failures) == 0, msg
|
291
298
|
|
299
|
+
|
292
300
|
def _complete_start_jobs(
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
301
|
+
action: Optional[List[str]] = None,
|
302
|
+
executor_keys: Optional[str] = None,
|
303
|
+
line: str = '',
|
304
|
+
**kw
|
305
|
+
) -> List[str]:
|
306
|
+
from meerschaum.utils.jobs import get_filtered_jobs
|
307
|
+
jobs = get_filtered_jobs(executor_keys, action)
|
299
308
|
if not action:
|
300
|
-
return
|
309
|
+
return list(jobs)
|
310
|
+
|
301
311
|
possibilities = []
|
302
312
|
_line_end = line.split(' ')[-1]
|
303
|
-
for
|
304
|
-
if
|
313
|
+
for name in jobs:
|
314
|
+
if name in action:
|
305
315
|
continue
|
306
316
|
if _line_end == '':
|
307
|
-
possibilities.append(
|
317
|
+
possibilities.append(name)
|
308
318
|
continue
|
309
|
-
if
|
310
|
-
possibilities.append(
|
319
|
+
if name.startswith(action[-1]):
|
320
|
+
possibilities.append(name)
|
311
321
|
return possibilities
|
312
322
|
|
313
323
|
|
meerschaum/actions/stop.py
CHANGED
@@ -50,11 +50,13 @@ def _complete_stop(
|
|
50
50
|
|
51
51
|
def _stop_jobs(
|
52
52
|
action: Optional[List[str]] = None,
|
53
|
+
executor_keys: Optional[str] = None,
|
53
54
|
timeout_seconds: Optional[int] = None,
|
54
55
|
noask: bool = False,
|
55
56
|
force: bool = False,
|
56
57
|
yes: bool = False,
|
57
58
|
nopretty: bool = False,
|
59
|
+
debug: bool = False,
|
58
60
|
**kw
|
59
61
|
) -> SuccessTuple:
|
60
62
|
"""
|
@@ -62,66 +64,93 @@ def _stop_jobs(
|
|
62
64
|
|
63
65
|
To see running processes, run `show jobs`.
|
64
66
|
"""
|
67
|
+
from meerschaum.utils.jobs import (
|
68
|
+
get_filtered_jobs,
|
69
|
+
get_running_jobs,
|
70
|
+
get_paused_jobs,
|
71
|
+
get_stopped_jobs,
|
72
|
+
get_restart_jobs,
|
73
|
+
)
|
65
74
|
from meerschaum.utils.formatting._jobs import pprint_jobs
|
66
75
|
from meerschaum.utils.daemon import (
|
67
76
|
get_filtered_daemons, get_running_daemons, get_stopped_daemons, get_paused_daemons,
|
68
77
|
)
|
69
78
|
from meerschaum.utils.warnings import warn
|
70
79
|
from meerschaum.utils.prompt import yes_no
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
80
|
+
|
81
|
+
jobs = get_filtered_jobs(executor_keys, action, warn=(not nopretty))
|
82
|
+
running_jobs = get_running_jobs(executor_keys, jobs)
|
83
|
+
paused_jobs = get_paused_jobs(executor_keys, jobs)
|
84
|
+
restart_jobs = get_restart_jobs(executor_keys, jobs)
|
85
|
+
stopped_jobs = {
|
86
|
+
name: job
|
87
|
+
for name, job in get_stopped_jobs(executor_keys, jobs).items()
|
88
|
+
if name not in restart_jobs
|
89
|
+
}
|
90
|
+
|
91
|
+
jobs_to_stop = {
|
92
|
+
**running_jobs,
|
93
|
+
**paused_jobs,
|
94
|
+
**restart_jobs,
|
95
|
+
}
|
96
|
+
|
97
|
+
if action and stopped_jobs and not nopretty:
|
76
98
|
warn(
|
77
|
-
|
78
|
-
|
79
|
-
|
99
|
+
"Skipping stopped job"
|
100
|
+
+ ("s" if len(stopped_jobs) != 1 else '')
|
101
|
+
+ " '"
|
102
|
+
+ ("', '".join(name for name in stopped_jobs)) + "'.",
|
103
|
+
stack=False,
|
80
104
|
)
|
81
105
|
|
82
|
-
|
83
|
-
|
84
|
-
return False, "No running or paused jobs to stop."
|
106
|
+
if not jobs_to_stop:
|
107
|
+
return False, "No running, paused or restarting jobs to stop."
|
85
108
|
|
86
109
|
if not action:
|
87
110
|
if not force:
|
88
|
-
pprint_jobs(
|
111
|
+
pprint_jobs(jobs_to_stop)
|
89
112
|
if not yes_no(
|
90
113
|
"Stop the above jobs?",
|
91
114
|
noask=noask, yes=yes, default='n'
|
92
115
|
):
|
93
116
|
return False, "No jobs were stopped."
|
94
117
|
|
95
|
-
|
96
|
-
for
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
warn(
|
103
|
-
f"Failed to gracefully quit job '{d.daemon_id}', attempting to terminate:\n "
|
104
|
-
+ f"{quit_msg}",
|
105
|
-
stack = False,
|
106
|
-
)
|
107
|
-
|
108
|
-
kill_success, kill_msg = d.kill(timeout=timeout_seconds)
|
109
|
-
if kill_success:
|
110
|
-
_kill_daemons.append(d)
|
111
|
-
continue
|
112
|
-
if not nopretty:
|
113
|
-
warn(f"Failed to kill job '{d.daemon_id}' (PID {d.pid}):\n{kill_msg}", stack=False)
|
118
|
+
job_success_tuples = {}
|
119
|
+
for name, job in jobs_to_stop.items():
|
120
|
+
stop_success, stop_msg = job.stop(
|
121
|
+
timeout_seconds=timeout_seconds,
|
122
|
+
debug=debug,
|
123
|
+
)
|
124
|
+
job_success_tuples[name] = (stop_success, stop_msg)
|
114
125
|
|
126
|
+
num_success = sum(
|
127
|
+
(
|
128
|
+
1
|
129
|
+
for name, (stop_success, stop_msg) in job_success_tuples.items()
|
130
|
+
if stop_success
|
131
|
+
)
|
132
|
+
)
|
133
|
+
num_fail = sum(
|
134
|
+
(
|
135
|
+
1
|
136
|
+
for name, (stop_success, stop_msg) in job_success_tuples.items()
|
137
|
+
if not stop_success
|
138
|
+
)
|
139
|
+
)
|
140
|
+
success = num_success > 0
|
115
141
|
msg = (
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
+ (("\n" if _quit_daemons else "")
|
120
|
-
+ ("Killed job" + ("s" if len(_kill_daemons) != 1 else '') +
|
121
|
-
" '" + "', '".join([d.daemon_id for d in _kill_daemons]) + "'.")
|
122
|
-
if _kill_daemons else '')
|
142
|
+
f"Stopped {num_success} job"
|
143
|
+
+ ('s' if num_success != 1 else '')
|
144
|
+
+ '.'
|
123
145
|
)
|
124
|
-
|
146
|
+
if num_fail > 0:
|
147
|
+
msg += (
|
148
|
+
f"\nFailed to stop {num_fail} job"
|
149
|
+
+ ('s' if num_fail != 1 else '')
|
150
|
+
+ '.'
|
151
|
+
)
|
152
|
+
|
153
|
+
return success, msg
|
125
154
|
|
126
155
|
|
127
156
|
### NOTE: This must be the final statement of the module.
|
meerschaum/api/_events.py
CHANGED
@@ -19,14 +19,20 @@ from meerschaum.utils.debug import dprint
|
|
19
19
|
from meerschaum.connectors.poll import retry_connect
|
20
20
|
from meerschaum.utils.warnings import warn
|
21
21
|
from meerschaum._internal.term.tools import is_webterm_running
|
22
|
+
from meerschaum.utils.jobs import start_check_jobs_thread, stop_check_jobs_thread
|
23
|
+
|
24
|
+
_check_jobs_thread = None
|
22
25
|
|
23
26
|
@app.on_event("startup")
|
24
27
|
async def startup():
|
25
|
-
|
28
|
+
"""
|
29
|
+
Connect to the instance database and begin monitoring jobs.
|
30
|
+
"""
|
26
31
|
try:
|
27
32
|
if not no_dash:
|
28
33
|
from meerschaum.api.dash.webterm import start_webterm
|
29
34
|
start_webterm()
|
35
|
+
|
30
36
|
connected = retry_connect(
|
31
37
|
get_api_connector(),
|
32
38
|
workers = get_uvicorn_config().get('workers', None),
|
@@ -36,18 +42,29 @@ async def startup():
|
|
36
42
|
import traceback
|
37
43
|
traceback.print_exc()
|
38
44
|
connected = False
|
45
|
+
|
39
46
|
if not connected:
|
40
47
|
await shutdown()
|
41
48
|
os._exit(1)
|
42
49
|
|
50
|
+
start_check_jobs_thread()
|
51
|
+
|
43
52
|
|
44
53
|
@app.on_event("shutdown")
|
45
54
|
async def shutdown():
|
55
|
+
"""
|
56
|
+
Close the database connection and stop monitoring jobs.
|
57
|
+
"""
|
46
58
|
if debug:
|
47
59
|
dprint("Closing connection...")
|
48
60
|
if get_api_connector().type == 'sql':
|
49
61
|
get_api_connector().engine.dispose()
|
50
62
|
|
63
|
+
stop_check_jobs_thread()
|
64
|
+
from meerschaum.api.routes._actions import _temp_jobs
|
65
|
+
for name, job in _temp_jobs.items():
|
66
|
+
job.delete()
|
67
|
+
|
51
68
|
### Terminate any running jobs left over.
|
52
69
|
if 'meerschaum.api.dash' in sys.modules:
|
53
70
|
from meerschaum.api.dash.actions import running_jobs, stop_action
|
meerschaum/api/_oauth2.py
CHANGED
@@ -30,6 +30,7 @@ class CustomOAuth2PasswordRequestForm:
|
|
30
30
|
self.client_id = client_id
|
31
31
|
self.client_secret = client_secret
|
32
32
|
|
33
|
+
|
33
34
|
LoginManager = fastapi_login.LoginManager
|
34
35
|
def generate_secret_key() -> str:
|
35
36
|
"""
|
@@ -46,5 +47,6 @@ def generate_secret_key() -> str:
|
|
46
47
|
|
47
48
|
return secret_key.encode('utf-8')
|
48
49
|
|
50
|
+
|
49
51
|
SECRET = generate_secret_key()
|
50
52
|
manager = LoginManager(SECRET, token_url=endpoints['login'])
|
meerschaum/api/_websockets.py
CHANGED
@@ -23,8 +23,8 @@ sessions = {}
|
|
23
23
|
@app.websocket('/dash/ws')
|
24
24
|
@app.websocket(_websocket_endpoint)
|
25
25
|
async def websocket_endpoint(
|
26
|
-
|
27
|
-
|
26
|
+
websocket: fastapi.WebSocket,
|
27
|
+
):
|
28
28
|
"""
|
29
29
|
Communicate with the Web Interface over a websocket.
|
30
30
|
"""
|
meerschaum/api/dash/jobs.py
CHANGED
@@ -16,6 +16,7 @@ from meerschaum.api import CHECK_UPDATE
|
|
16
16
|
dbc = attempt_import('dash_bootstrap_components', lazy=False, check_update=CHECK_UPDATE)
|
17
17
|
html, dcc = import_html(), import_dcc()
|
18
18
|
dateutil_parser = attempt_import('dateutil.parser', check_update=CHECK_UPDATE)
|
19
|
+
from meerschaum.utils.jobs import get_jobs, Job
|
19
20
|
from meerschaum.utils.daemon import (
|
20
21
|
get_daemons,
|
21
22
|
get_running_daemons,
|
@@ -38,13 +39,15 @@ def get_jobs_cards(state: WebState):
|
|
38
39
|
Build cards and alerts lists for jobs.
|
39
40
|
"""
|
40
41
|
daemons = get_daemons()
|
42
|
+
jobs = get_jobs()
|
41
43
|
session_id = state['session-store.data'].get('session-id', None)
|
42
44
|
is_authenticated = is_session_authenticated(session_id)
|
43
45
|
|
44
46
|
alert = alert_from_success_tuple(daemons)
|
45
47
|
cards = []
|
46
48
|
|
47
|
-
for
|
49
|
+
for name, job in jobs.items():
|
50
|
+
d = job.daemon
|
48
51
|
footer_children = html.Div(
|
49
52
|
build_process_timestamps_children(d),
|
50
53
|
id = {'type': 'process-timestamps-div', 'index': d.daemon_id},
|
@@ -80,7 +83,7 @@ def get_jobs_cards(state: WebState):
|
|
80
83
|
]
|
81
84
|
|
82
85
|
body_children = [
|
83
|
-
html.H4(html.B(
|
86
|
+
html.H4(html.B(name), className="card-title"),
|
84
87
|
html.Div(
|
85
88
|
html.P(
|
86
89
|
d.label,
|
@@ -8,6 +8,7 @@ Import all routes from other modules in package
|
|
8
8
|
|
9
9
|
from meerschaum.api.routes._login import *
|
10
10
|
from meerschaum.api.routes._actions import *
|
11
|
+
from meerschaum.api.routes._jobs import *
|
11
12
|
from meerschaum.api.routes._connectors import *
|
12
13
|
from meerschaum.api.routes._index import *
|
13
14
|
from meerschaum.api.routes._misc import *
|