manta-node 0.6b5.dev771__py3-none-any.whl → 0.6b5.dev773__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/cli/_version_generated.py +3 -3
- manta_node/supervisor/lifecycle.py +69 -29
- manta_node/supervisor/switch.py +7 -3
- {manta_node-0.6b5.dev771.dist-info → manta_node-0.6b5.dev773.dist-info}/METADATA +1 -1
- {manta_node-0.6b5.dev771.dist-info → manta_node-0.6b5.dev773.dist-info}/RECORD +9 -9
- {manta_node-0.6b5.dev771.dist-info → manta_node-0.6b5.dev773.dist-info}/WHEEL +0 -0
- {manta_node-0.6b5.dev771.dist-info → manta_node-0.6b5.dev773.dist-info}/entry_points.txt +0 -0
- {manta_node-0.6b5.dev771.dist-info → manta_node-0.6b5.dev773.dist-info}/licenses/LICENSE +0 -0
- {manta_node-0.6b5.dev771.dist-info → manta_node-0.6b5.dev773.dist-info}/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ This file is auto-generated at build time by scripts/generate_version.py.
|
|
|
4
4
|
Do not edit manually.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "2026.10.
|
|
8
|
-
__build_date__ = "2026.10.
|
|
9
|
-
__commit_id__ = "
|
|
7
|
+
__version__ = "2026.10.08.22eaa34f"
|
|
8
|
+
__build_date__ = "2026.10.08"
|
|
9
|
+
__commit_id__ = "22eaa34f"
|
|
10
10
|
__package_version__ = "0.6b5" # release-series base, moved by scripts/bump_version.py
|
|
@@ -17,6 +17,7 @@ supervisor.
|
|
|
17
17
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
+
import sys
|
|
20
21
|
import time
|
|
21
22
|
from collections.abc import Callable
|
|
22
23
|
from dataclasses import dataclass
|
|
@@ -128,15 +129,17 @@ def run_switch(
|
|
|
128
129
|
nonlocal candidate_python
|
|
129
130
|
candidate_python = fetch(request.target)
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
cause = _within(bounds.fetch, do_fetch)
|
|
133
|
+
if cause is not None:
|
|
134
|
+
return _step_failed(
|
|
135
|
+
request, "fetch", "fetch exceeded its bound (no switch)", cause
|
|
134
136
|
)
|
|
135
137
|
|
|
136
138
|
# VERIFY — the candidate must be usable in its OWN environment (NF-2): the
|
|
137
139
|
# fetcher named the interpreter the candidate will run from.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
cause = _within(bounds.verify, lambda: verify(candidate_dir, candidate_python))
|
|
141
|
+
if cause is not None:
|
|
142
|
+
return _step_failed(request, "verify", "verification failed (no switch)", cause)
|
|
140
143
|
|
|
141
144
|
# FREE SPACE — refuse before staging when there is no room for a full version
|
|
142
145
|
# dir (NF-12, §6.2). Refusing here, before any write, is what stops a
|
|
@@ -156,8 +159,11 @@ def run_switch(
|
|
|
156
159
|
candidate_dir, candidate_python
|
|
157
160
|
)
|
|
158
161
|
|
|
159
|
-
|
|
160
|
-
|
|
162
|
+
cause = _within(bounds.stage, do_stage)
|
|
163
|
+
if cause is not None:
|
|
164
|
+
return _step_failed(
|
|
165
|
+
request, "stage", "stage exceeded its bound or failed", cause
|
|
166
|
+
)
|
|
161
167
|
target = staged["target"]
|
|
162
168
|
|
|
163
169
|
record = InFlight(
|
|
@@ -169,25 +175,26 @@ def run_switch(
|
|
|
169
175
|
write_inflight(record)
|
|
170
176
|
|
|
171
177
|
# SWITCH — the commit point (NF-1), bounded.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
clear_inflight()
|
|
175
|
-
_reclaim_candidate(bounds, target, last_good_dir)
|
|
176
|
-
return _outcome(
|
|
177
|
-
request, SeamState.FAILED, "switch exceeded its bound (repoint failed)"
|
|
178
|
-
)
|
|
179
|
-
except VersionTreeError as exc:
|
|
178
|
+
cause = _within(bounds.switch, lambda: version_tree.commit(target))
|
|
179
|
+
if cause is not None:
|
|
180
180
|
clear_inflight()
|
|
181
181
|
_reclaim_candidate(bounds, target, last_good_dir)
|
|
182
|
-
return
|
|
182
|
+
return _step_failed(request, "switch", "switch failed (repoint failed)", cause)
|
|
183
183
|
|
|
184
184
|
# RESTART onto the committed version, then wait for the return window. A
|
|
185
185
|
# restart that raises is a failed switch, not a crash: surface DOWN and clear
|
|
186
186
|
# the record rather than letting the exception escape.
|
|
187
|
-
|
|
187
|
+
cause = _within(bounds.switch, restart)
|
|
188
|
+
if cause is not None:
|
|
188
189
|
clear_inflight()
|
|
189
190
|
_reclaim_candidate(bounds, target, last_good_dir)
|
|
190
|
-
return
|
|
191
|
+
return _step_failed(
|
|
192
|
+
request,
|
|
193
|
+
"restart",
|
|
194
|
+
"restart failed after the switch",
|
|
195
|
+
cause,
|
|
196
|
+
state=SeamState.DOWN,
|
|
197
|
+
)
|
|
191
198
|
|
|
192
199
|
if is_back(record.deadline_epoch):
|
|
193
200
|
clear_inflight()
|
|
@@ -215,12 +222,19 @@ def run_switch(
|
|
|
215
222
|
)
|
|
216
223
|
try:
|
|
217
224
|
version_tree.commit(version_tree.versions_dir() / last_good)
|
|
218
|
-
|
|
219
|
-
|
|
225
|
+
cause = _within(bounds.switch, restart)
|
|
226
|
+
if cause is not None:
|
|
227
|
+
raise LifecycleError(f"restart after revert failed: {cause}")
|
|
220
228
|
except (VersionTreeError, LifecycleError) as exc:
|
|
221
229
|
clear_inflight()
|
|
222
230
|
_reclaim_candidate(bounds, target, last_good_dir)
|
|
223
|
-
return
|
|
231
|
+
return _step_failed(
|
|
232
|
+
request,
|
|
233
|
+
"revert",
|
|
234
|
+
f"revert failed: {exc}",
|
|
235
|
+
str(exc),
|
|
236
|
+
state=SeamState.DOWN,
|
|
237
|
+
)
|
|
224
238
|
clear_inflight()
|
|
225
239
|
# The candidate was superseded the moment the switch did not land: it is
|
|
226
240
|
# reclaimed even though the switch failed, so repeated failing switches do
|
|
@@ -257,17 +271,43 @@ def _reclaim_candidate(
|
|
|
257
271
|
version_tree.reclaim(bounds.retention_dirs, protect)
|
|
258
272
|
|
|
259
273
|
|
|
260
|
-
def _within(bound: float, step: Callable[[], None]) ->
|
|
261
|
-
"""Run ``step``;
|
|
274
|
+
def _within(bound: float, step: Callable[[], None]) -> str | None:
|
|
275
|
+
"""Run ``step``; return None if it completed within ``bound``, else the cause.
|
|
262
276
|
|
|
263
277
|
A step that raises is a failure of that state, not a crash: before the switch
|
|
264
|
-
it leaves the node on its current version (NF-3). The
|
|
265
|
-
|
|
266
|
-
|
|
278
|
+
it leaves the node on its current version (NF-3). The return names the
|
|
279
|
+
failure — the exception, or the bound it exceeded — so the caller can record
|
|
280
|
+
the stage and its cause. The time bound is enforced by the step itself (a
|
|
281
|
+
subprocess timeout / an HTTP timeout); this records the comparison so the
|
|
282
|
+
caller does not have to.
|
|
267
283
|
"""
|
|
268
284
|
start = time.monotonic()
|
|
269
285
|
try:
|
|
270
286
|
step()
|
|
271
|
-
except Exception:
|
|
272
|
-
return
|
|
273
|
-
|
|
287
|
+
except Exception as exc:
|
|
288
|
+
return f"{type(exc).__name__}: {exc}"
|
|
289
|
+
elapsed = time.monotonic() - start
|
|
290
|
+
if elapsed > bound:
|
|
291
|
+
return f"exceeded its {bound}s bound ({elapsed:.1f}s)"
|
|
292
|
+
return None
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def _step_failed(
|
|
296
|
+
request: UpdateRequest,
|
|
297
|
+
stage: str,
|
|
298
|
+
reason: str,
|
|
299
|
+
cause: str,
|
|
300
|
+
*,
|
|
301
|
+
state: SeamState = SeamState.FAILED,
|
|
302
|
+
) -> SwitchOutcome:
|
|
303
|
+
"""Build a failure outcome naming the stage and cause, and log it.
|
|
304
|
+
|
|
305
|
+
``detail`` always carries ``stage`` and ``cause`` together, and the failed
|
|
306
|
+
stage always logs a line to stderr (the supervisor's journal) before
|
|
307
|
+
returning, so the outcome and the journal name the same failure.
|
|
308
|
+
"""
|
|
309
|
+
print(
|
|
310
|
+
f"supervisor: {stage} failed for request {request.request_id}: {cause}",
|
|
311
|
+
file=sys.stderr,
|
|
312
|
+
)
|
|
313
|
+
return _outcome(request, state, reason, stage=stage, cause=cause)
|
manta_node/supervisor/switch.py
CHANGED
|
@@ -156,15 +156,19 @@ def read_manifest(version_dir: Path) -> Version | None:
|
|
|
156
156
|
def materialise_version(version: str, python: str) -> Path:
|
|
157
157
|
"""Create an immutable version dir for ``version``; return its path.
|
|
158
158
|
|
|
159
|
-
Idempotent: an existing dir
|
|
160
|
-
|
|
159
|
+
Idempotent: an existing dir is returned unchanged when its identity matches
|
|
160
|
+
``version`` — the manifest's node version, or the legacy pair id it was
|
|
161
|
+
materialised under. The fleet path still names a candidate by its pair
|
|
162
|
+
(`manta-node@X+manta-common-core@Y`) and pre-materialises that dir, so
|
|
163
|
+
matching the pair too is what keeps its apply from being rejected as "not a
|
|
164
|
+
valid version dir" (#520).
|
|
161
165
|
"""
|
|
162
166
|
if not is_safe_version_name(version):
|
|
163
167
|
raise VersionTreeError(f"refusing an unsafe version dir name: {version!r}")
|
|
164
168
|
target = versions_dir() / version
|
|
165
169
|
if target.exists():
|
|
166
170
|
existing = read_manifest(target)
|
|
167
|
-
if existing and existing.version
|
|
171
|
+
if existing is not None and version in (existing.version, existing.pair):
|
|
168
172
|
return target
|
|
169
173
|
raise VersionTreeError(
|
|
170
174
|
f"{target} exists but is not a valid version dir for {version!r}"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: manta_node
|
|
3
|
-
Version: 0.6b5.
|
|
3
|
+
Version: 0.6b5.dev773
|
|
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 <hugo.miralles@manta-tech.io>, Matthew Thompson <matthew.thompson@manta-tech.io>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -7,7 +7,7 @@ manta_node/tasks.py,sha256=o837Hi-KFVJg9LF5iOtE8oD6UuTOfrEPWR-JOdhRGeY,6983
|
|
|
7
7
|
manta_node/update_path.py,sha256=6N_bN9z8MqnyWWfGTe1-aJFijf2tSy_IvO6VHvNSQVU,1667
|
|
8
8
|
manta_node/utils.py,sha256=Hw4Iw2jYQYsfVLVJuBMt-_rMFBeml3nCDE2jiiXc8YM,1155
|
|
9
9
|
manta_node/cli/__init__.py,sha256=arzO3mXDJ-E2yeeytbZfN7mCswwxdQ43_QjyeL2E5yE,134
|
|
10
|
-
manta_node/cli/_version_generated.py,sha256=
|
|
10
|
+
manta_node/cli/_version_generated.py,sha256=u15js_niq-wLlcE1Hitgt0MvKozxGxx0dZjNV-EhUfc,332
|
|
11
11
|
manta_node/cli/config_manager.py,sha256=BCju9zqzraviL3KrzRnB-vZQUY__Q5kuEqb7EdB8YdI,4409
|
|
12
12
|
manta_node/cli/main.py,sha256=dZa6zrypWBvpN8hd4qpxevvlyNFhxKINCg1537NJ36w,4318
|
|
13
13
|
manta_node/cli/version.py,sha256=L4lNTz-Uw_ejumy1tXJcJhcjhb-5FRcRQ6ogZM5N1Xo,5136
|
|
@@ -57,15 +57,15 @@ manta_node/supervisor/__init__.py,sha256=kgdoNce1tM4e7jvdxkdmnNJV1L92-NI2cRfYSdm
|
|
|
57
57
|
manta_node/supervisor/bounds.py,sha256=MlUfj0tYY-US348JsxYA-Ph5pSpgoOPlRdVTwmrPtZA,3181
|
|
58
58
|
manta_node/supervisor/executor.py,sha256=HwER4Q9uFI4cYTBEn5BFtRhU69Wdj9fj8-RQZ6u8T8o,8171
|
|
59
59
|
manta_node/supervisor/inflight.py,sha256=GhngTFmFKi0P3yqu5P5XeRP5G-H8vG-uQcAzdjATdm0,4515
|
|
60
|
-
manta_node/supervisor/lifecycle.py,sha256=
|
|
60
|
+
manta_node/supervisor/lifecycle.py,sha256=_-Tzb3Ipu_RERC5T8DeHyy7BS5RypIc8rIz2GvKRG2s,12000
|
|
61
61
|
manta_node/supervisor/process.py,sha256=frbbgvhLsveXMzwmRkNmB3FEKKgqiEdG6UhffRrE_Bw,20741
|
|
62
62
|
manta_node/supervisor/records.py,sha256=fUlL1SfmWpGnCbJ9956cuy0H3a7-aEF-B-naqbJiYoU,6405
|
|
63
63
|
manta_node/supervisor/seam.py,sha256=4kczRku5Ctn4xRvXS-pyzaDFau7LnX5bYOn6IRNKRyE,9665
|
|
64
64
|
manta_node/supervisor/sequence.py,sha256=eYu7rrk1ecc4Y2jQhhJ7CopPz3m0lOsFLJj5lT2PwBw,1685
|
|
65
|
-
manta_node/supervisor/switch.py,sha256=
|
|
66
|
-
manta_node-0.6b5.
|
|
67
|
-
manta_node-0.6b5.
|
|
68
|
-
manta_node-0.6b5.
|
|
69
|
-
manta_node-0.6b5.
|
|
70
|
-
manta_node-0.6b5.
|
|
71
|
-
manta_node-0.6b5.
|
|
65
|
+
manta_node/supervisor/switch.py,sha256=ansCCmxru9bmmLggq8b68gmnyqbPgXF_u2Z6fo_xSMo,22283
|
|
66
|
+
manta_node-0.6b5.dev773.dist-info/licenses/LICENSE,sha256=9mBgLhiB9goQPQjg9XQJ6FjgVxYw9Q8lyOZYkPGwF_c,34484
|
|
67
|
+
manta_node-0.6b5.dev773.dist-info/METADATA,sha256=soD8Yq0AvgXQSmpobHn-TAuOENMsdutClUYPOKjZXk4,4937
|
|
68
|
+
manta_node-0.6b5.dev773.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
69
|
+
manta_node-0.6b5.dev773.dist-info/entry_points.txt,sha256=uCwggRApalLEsYs1YxwTBN0-e9oMJAkMoBp01HaSdoY,110
|
|
70
|
+
manta_node-0.6b5.dev773.dist-info/top_level.txt,sha256=nbT5J5WETuXM9UPoQckl29uUOq8wMYdRb9QDx5kAFeo,11
|
|
71
|
+
manta_node-0.6b5.dev773.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|