manta-node 0.5b0.dev91__py3-none-any.whl → 0.5b0.dev116__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.
- manta_node/infrastructure/mqtt/command_handler.py +59 -41
- manta_node/task_manager.py +23 -4
- {manta_node-0.5b0.dev91.dist-info → manta_node-0.5b0.dev116.dist-info}/METADATA +1 -1
- {manta_node-0.5b0.dev91.dist-info → manta_node-0.5b0.dev116.dist-info}/RECORD +8 -8
- {manta_node-0.5b0.dev91.dist-info → manta_node-0.5b0.dev116.dist-info}/WHEEL +0 -0
- {manta_node-0.5b0.dev91.dist-info → manta_node-0.5b0.dev116.dist-info}/entry_points.txt +0 -0
- {manta_node-0.5b0.dev91.dist-info → manta_node-0.5b0.dev116.dist-info}/licenses/LICENSE +0 -0
- {manta_node-0.5b0.dev91.dist-info → manta_node-0.5b0.dev116.dist-info}/top_level.txt +0 -0
|
@@ -10,7 +10,7 @@ import aiomqtt
|
|
|
10
10
|
from manta_common.base_mqtt import MqttBase
|
|
11
11
|
from manta_common.build.common.mqtt import MqMetricsSnapshot, MqTaskUpdate
|
|
12
12
|
from manta_common.build.common.system import Logs
|
|
13
|
-
from manta_common.build.common.tasks import TaskStatus, TaskUpdate
|
|
13
|
+
from manta_common.build.common.tasks import MqttTask, TaskStatus, TaskUpdate
|
|
14
14
|
from manta_common.const import CHUNK_SIZE
|
|
15
15
|
from manta_common.conversions import ID
|
|
16
16
|
from manta_common.errors import (
|
|
@@ -121,52 +121,41 @@ class CommandHandler(TaskManager, Collector, MqttBase):
|
|
|
121
121
|
except Exception:
|
|
122
122
|
self.tracer.exception("Error when closing Docker client")
|
|
123
123
|
|
|
124
|
+
async def main(self):
|
|
125
|
+
"""
|
|
126
|
+
Override MqttBase.main to run task checker as a background task
|
|
127
|
+
alongside the MQTT message loop.
|
|
128
|
+
"""
|
|
129
|
+
self.tracer.debug("Starting background task checker")
|
|
130
|
+
checker = asyncio.create_task(self._ping_loop())
|
|
131
|
+
try:
|
|
132
|
+
await MqttBase.main(self)
|
|
133
|
+
finally:
|
|
134
|
+
checker.cancel()
|
|
135
|
+
try:
|
|
136
|
+
await checker
|
|
137
|
+
except asyncio.CancelledError:
|
|
138
|
+
pass
|
|
139
|
+
|
|
124
140
|
async def loop_tasks(self):
|
|
125
141
|
"""
|
|
126
|
-
|
|
142
|
+
Delegate to base class MQTT loop (subscribe + publish only).
|
|
143
|
+
Task checking runs independently in the background via main().
|
|
144
|
+
"""
|
|
145
|
+
await MqttBase.loop_tasks(self)
|
|
146
|
+
|
|
147
|
+
async def _ping_loop(self):
|
|
148
|
+
"""
|
|
149
|
+
Background loop that periodically checks task statuses and
|
|
150
|
+
sends heartbeats. Runs independently of the MQTT connection state.
|
|
127
151
|
"""
|
|
128
152
|
while True:
|
|
129
|
-
# Wait until we either (1) receive a message or (2) publish a message
|
|
130
153
|
try:
|
|
131
|
-
|
|
132
|
-
publish_task = asyncio.create_task(self.queue.get())
|
|
133
|
-
ping_task = asyncio.create_task(self._ping())
|
|
134
|
-
done, _ = await asyncio.wait(
|
|
135
|
-
(subscribe_task, publish_task, ping_task),
|
|
136
|
-
return_when=asyncio.FIRST_COMPLETED,
|
|
137
|
-
)
|
|
138
|
-
# If the asyncio.wait is cancelled, we must also cancel the queue task
|
|
154
|
+
await self._ping()
|
|
139
155
|
except asyncio.CancelledError:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
raise
|
|
144
|
-
|
|
145
|
-
# When we receive a message, process it
|
|
146
|
-
if subscribe_task in done and publish_task in done:
|
|
147
|
-
await self._subscribe_from_task(subscribe_task)
|
|
148
|
-
await self._publish_from_task(publish_task)
|
|
149
|
-
ping_task.cancel()
|
|
150
|
-
elif subscribe_task in done:
|
|
151
|
-
await self._subscribe_from_task(subscribe_task)
|
|
152
|
-
publish_task.cancel()
|
|
153
|
-
ping_task.cancel()
|
|
154
|
-
# Publish the message to its topic with specific QoS
|
|
155
|
-
elif publish_task in done:
|
|
156
|
-
await self._publish_from_task(publish_task)
|
|
157
|
-
subscribe_task.cancel()
|
|
158
|
-
ping_task.cancel()
|
|
159
|
-
# If we disconnect from the broker, stop the loop with an exception
|
|
160
|
-
elif ping_task in done:
|
|
161
|
-
ping_task.cancel()
|
|
162
|
-
publish_task.cancel()
|
|
163
|
-
subscribe_task.cancel()
|
|
164
|
-
else:
|
|
165
|
-
self.tracer.warning("Disconnected during message iteration")
|
|
166
|
-
publish_task.cancel()
|
|
167
|
-
subscribe_task.cancel()
|
|
168
|
-
ping_task.cancel()
|
|
169
|
-
raise aiomqtt.MqttError("Disconnected during message iteration")
|
|
156
|
+
break
|
|
157
|
+
except Exception:
|
|
158
|
+
self.tracer.exception("Unhandled error in ping loop, continuing...")
|
|
170
159
|
|
|
171
160
|
async def _ping(self):
|
|
172
161
|
"""
|
|
@@ -313,3 +302,32 @@ class CommandHandler(TaskManager, Collector, MqttBase):
|
|
|
313
302
|
Node ID to stop
|
|
314
303
|
"""
|
|
315
304
|
await self.stop_callback()
|
|
305
|
+
|
|
306
|
+
async def on_task_setup_failed(self, task: MqttTask, exc: Exception):
|
|
307
|
+
"""
|
|
308
|
+
Publish a FAILED task update when task setup fails.
|
|
309
|
+
|
|
310
|
+
Parameters
|
|
311
|
+
----------
|
|
312
|
+
task : MqttTask
|
|
313
|
+
Task that failed to setup
|
|
314
|
+
exc : Exception
|
|
315
|
+
The exception that caused the failure
|
|
316
|
+
"""
|
|
317
|
+
task_update = TaskUpdate(
|
|
318
|
+
swarm_id=task.swarm_id,
|
|
319
|
+
node_id=self.tracer.metadata.node_id,
|
|
320
|
+
task_id=task.task_id,
|
|
321
|
+
iteration=task.iteration,
|
|
322
|
+
circular=task.circular,
|
|
323
|
+
task_status=TaskStatus.FAILED,
|
|
324
|
+
)
|
|
325
|
+
try:
|
|
326
|
+
await self.publish_task_update(task_update)
|
|
327
|
+
self.tracer.info(
|
|
328
|
+
f"Published FAILED status for task {task.task_id} after setup failure"
|
|
329
|
+
)
|
|
330
|
+
except Exception as publish_exc:
|
|
331
|
+
self.tracer.exception(
|
|
332
|
+
f"Failed to publish FAILED status for task {task.task_id}: {repr(publish_exc)}"
|
|
333
|
+
)
|
manta_node/task_manager.py
CHANGED
|
@@ -352,12 +352,31 @@ class TaskManager(ContainerManager, ImageExecutor):
|
|
|
352
352
|
swarm_id = ID(task.swarm_id)
|
|
353
353
|
self.tracer.info(f"Deploying task {task_id}")
|
|
354
354
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
355
|
+
try:
|
|
356
|
+
if (swarm_id.tid, task_id.tid) in self.tasks:
|
|
357
|
+
await self.restart_task(self.tasks[(swarm_id.tid, task_id.tid)], task)
|
|
358
|
+
else:
|
|
359
|
+
await self.create_task(task)
|
|
360
|
+
except Exception as exc:
|
|
361
|
+
self.tracer.exception(f"Task {task_id} setup failed: {repr(exc)}")
|
|
362
|
+
await self.on_task_setup_failed(task, exc)
|
|
363
|
+
raise
|
|
359
364
|
return task_id
|
|
360
365
|
|
|
366
|
+
async def on_task_setup_failed(self, task: MqttTask, exc: Exception):
|
|
367
|
+
"""
|
|
368
|
+
Hook called when task setup fails. Override in subclasses to handle
|
|
369
|
+
failure notifications (e.g., publish MQTT update).
|
|
370
|
+
|
|
371
|
+
Parameters
|
|
372
|
+
----------
|
|
373
|
+
task : MqttTask
|
|
374
|
+
Task that failed to setup
|
|
375
|
+
exc : Exception
|
|
376
|
+
The exception that caused the failure
|
|
377
|
+
"""
|
|
378
|
+
pass
|
|
379
|
+
|
|
361
380
|
async def restart_task(self, task_progression: TaskProgression, task: MqttTask):
|
|
362
381
|
"""
|
|
363
382
|
Restart a task
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: manta_node
|
|
3
|
-
Version: 0.5b0.
|
|
3
|
+
Version: 0.5b0.dev116
|
|
4
4
|
Summary: Node side software of the Manta platform. It is responsible for the communication with the Manta Core and the execution of the tasks.
|
|
5
5
|
Author-email: Hugo Miralles <hugomiralles@manta-tech.io>, Matthew Thompson <matthew.thompson@manta-tech.io>
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
manta_node/__init__.py,sha256=bgGWXH3yQVhNf0v1ZGUBAy5Y51fqb0Y-EaLnocbcino,153
|
|
2
2
|
manta_node/__main__.py,sha256=0VzbY1KfezaARZDuCBc7Th1GO_-BnKTK8eDEXhgP5J4,1731
|
|
3
3
|
manta_node/node_orchestrator.py,sha256=0VMBsZSMQiIe9L-Bd7Jn4avNpNyDCMa1kyPSTgRiOes,17336
|
|
4
|
-
manta_node/task_manager.py,sha256=
|
|
4
|
+
manta_node/task_manager.py,sha256=cusrPrctHC4NY6Ryb_hu9BCEVi2DUceu99H-56ztVTA,20523
|
|
5
5
|
manta_node/tasks.py,sha256=W__XjU17AX8VqOtgy8HRBmxWtVufTkFvri8s8Y3R394,6721
|
|
6
6
|
manta_node/utils.py,sha256=gkYRB7fylk1jy1sm7nKU7o8eadGxn0AX4IjCHT6Wzuw,1179
|
|
7
7
|
manta_node/cli/__init__.py,sha256=arzO3mXDJ-E2yeeytbZfN7mCswwxdQ43_QjyeL2E5yE,134
|
|
@@ -34,10 +34,10 @@ manta_node/infrastructure/metrics/__init__.py,sha256=ODGAj9s63F5jba2c3dQRMfNK6I4
|
|
|
34
34
|
manta_node/infrastructure/metrics/collector.py,sha256=nhFPAbjA04ye3UaGN95_zdpf9hLs2lrMXwOwKlFKYsI,3070
|
|
35
35
|
manta_node/infrastructure/metrics/metrics_collector.py,sha256=jhEocAPWS6xgbNvcBBiEB9cAN_9hEGssZJXoysQzWOk,10518
|
|
36
36
|
manta_node/infrastructure/mqtt/__init__.py,sha256=riXo1sXgO4YV6DHCmWRqK61BAmuGLdHiVdQFunAJadA,140
|
|
37
|
-
manta_node/infrastructure/mqtt/command_handler.py,sha256=
|
|
38
|
-
manta_node-0.5b0.
|
|
39
|
-
manta_node-0.5b0.
|
|
40
|
-
manta_node-0.5b0.
|
|
41
|
-
manta_node-0.5b0.
|
|
42
|
-
manta_node-0.5b0.
|
|
43
|
-
manta_node-0.5b0.
|
|
37
|
+
manta_node/infrastructure/mqtt/command_handler.py,sha256=mnMYIjTqfAL14k73s3ab_fBeCtgBKU9V86VWFFrZN1k,11923
|
|
38
|
+
manta_node-0.5b0.dev116.dist-info/licenses/LICENSE,sha256=P5HojupjKoAusNtHqWOvO-YFolwLFWQ7Uq0XVKK9nFQ,35291
|
|
39
|
+
manta_node-0.5b0.dev116.dist-info/METADATA,sha256=pVmpSnFpw8_1lUb7YGkQzOAW9afEaS0nMNlVRwFf9HY,44654
|
|
40
|
+
manta_node-0.5b0.dev116.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
41
|
+
manta_node-0.5b0.dev116.dist-info/entry_points.txt,sha256=C_zcw6mdmztNxVUZGLZ83UH5TwcSuqb2C-rB4e2CQoc,56
|
|
42
|
+
manta_node-0.5b0.dev116.dist-info/top_level.txt,sha256=nbT5J5WETuXM9UPoQckl29uUOq8wMYdRb9QDx5kAFeo,11
|
|
43
|
+
manta_node-0.5b0.dev116.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|