- V7.1.1: /swarm/check no longer returns raw exception text; logs detail server-side, returns generic 'probe failed'. - BUG-1: register EditAction -> SSHDriver so edit ticks no longer crash. - BUG-2: topology reconcile matches generator-named deckies by expected-name membership instead of a hyphen heuristic. - BUG-3: intel provider lookups acquire the per-provider semaphore so declared concurrency bounds are enforced. - BUG-4: RuleIndex.install evicts a rule from kinds it no longer applies to. - BUG-5: UnixSocketBus.connect() is lock-guarded with a double-check so concurrent first-connects open exactly one socket and reader task. - BUG-6/V5.1.3: multi-token JSON-field search binds each token to a distinct parameter instead of collapsing to the last value. Regression tests added for every fix, verified red-before/green-after. V4.1.1c/V12.1.1 (updater master-CN gate) and V12.5.1 (tarball include-list) confirmed already fixed in prior commits and left untouched.
76 lines
2.8 KiB
Python
76 lines
2.8 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""Activity drivers for the orchestrator.
|
|
|
|
Concrete drivers register dispatch in :func:`get_driver_for`. Same
|
|
lazy-import pattern as :mod:`decnet.canary.factory`: the import-time
|
|
cost of :mod:`decnet.orchestrator.drivers` stays low for callers that
|
|
only need :class:`ActivityResult` / :class:`ActivityDriver`.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from decnet.orchestrator.drivers.base import (
|
|
ActivityDriver,
|
|
ActivityResult,
|
|
Driver,
|
|
)
|
|
from decnet.orchestrator.scheduler import Action, EditAction, FileAction, TrafficAction
|
|
|
|
__all__ = [
|
|
"ActivityDriver",
|
|
"ActivityResult",
|
|
"Driver",
|
|
"SSHDriver",
|
|
"get_driver_for",
|
|
]
|
|
|
|
|
|
def __getattr__(name: str): # pragma: no cover - import passthrough
|
|
"""Lazy access to concrete drivers.
|
|
|
|
Avoids dragging the docker-exec / email-driver code into every
|
|
consumer that only needs the ABC.
|
|
"""
|
|
if name == "SSHDriver":
|
|
from decnet.orchestrator.drivers.ssh import SSHDriver
|
|
return SSHDriver
|
|
if name == "EmailDriver":
|
|
from decnet.orchestrator.drivers.email import EmailDriver
|
|
return EmailDriver
|
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
|
|
|
|
def get_driver_for(action: Action) -> ActivityDriver:
|
|
"""Return the concrete driver that handles *action*.
|
|
|
|
Stage 4 of the realism migration adds this seam so the orchestrator
|
|
worker can dispatch by action type without an isinstance chain in
|
|
``_one_tick``. Stage 5 wires the worker to call this function
|
|
instead of holding a single ``SSHDriver`` instance.
|
|
|
|
The set of action shapes the orchestrator can plan grows with the
|
|
migration:
|
|
|
|
* :class:`TrafficAction` / :class:`FileAction` → :class:`SSHDriver`
|
|
* :class:`EmailAction` (post-stage-5) → ``EmailDriver``
|
|
* :class:`EditAction` (post-stage-3b) → :class:`SSHDriver`
|
|
"""
|
|
# Lazy imports keep the side-effecting docker-exec / email-driver
|
|
# modules out of every importer's graph.
|
|
from decnet.orchestrator.drivers.ssh import SSHDriver
|
|
|
|
if isinstance(action, (TrafficAction, FileAction, EditAction)):
|
|
return SSHDriver()
|
|
# EmailAction lands in stage 5; reachable only after that import is
|
|
# added to scheduler. Importing inside the branch avoids a cycle
|
|
# with realism.llm at module load time.
|
|
try:
|
|
from decnet.orchestrator.emailgen.scheduler import EmailAction
|
|
except ImportError: # pragma: no cover - scheduler always exists
|
|
EmailAction = None # type: ignore[misc]
|
|
if EmailAction is not None and isinstance(action, EmailAction):
|
|
from decnet.orchestrator.drivers.email import EmailDriver
|
|
return EmailDriver()
|
|
raise TypeError(
|
|
f"no driver registered for action type {type(action).__name__}"
|
|
)
|