Add reusable local HTTP job service for Blender add-ons

- Implement JobClient for handling HTTP requests to the JobServer.
- Create ModalJobOperatorBase for managing Blender job lifecycle.
- Introduce JobContext and JobServer for job management and state handling.
- Add ServiceConnection and ServiceController for managing service processes.
- Implement job submission, cancellation, and resource management endpoints in the server.
- Ensure proper error handling and job state updates throughout the service.
This commit is contained in:
2026-08-16 21:04:10 +08:00
parent 0c8d3a8988
commit b3a07cde32
43 changed files with 2600 additions and 2671 deletions

View File

@@ -19,7 +19,7 @@ PROJECT_ROOT = Path(__file__).resolve().parents[1]
def load_worker():
specification = importlib.util.spec_from_file_location(
"snapform_worker",
PROJECT_ROOT / "src" / "snapform" / "worker.py",
PROJECT_ROOT / "src" / "snapform" / "ai_service" / "jobs.py",
)
module = importlib.util.module_from_spec(specification)
specification.loader.exec_module(module)
@@ -500,18 +500,18 @@ class WorkerTest(unittest.TestCase):
def test_models_from_r2_roundtrip_preserves_fields(self):
root = PROJECT_ROOT / ".tmp-models-from-r2"
model_dir = root / "models" / "DA3"
discovery = root / "service.json"
runtime_state = root / "runtime.json"
try:
discovery.parent.mkdir(parents=True, exist_ok=True)
discovery.write_text(
json.dumps({"port": 1, "token": "t"}),
runtime_state.parent.mkdir(parents=True, exist_ok=True)
runtime_state.write_text(
json.dumps({"keep": "value"}),
encoding="utf-8",
)
self.assertFalse(self.worker._models_from_r2(model_dir))
self.worker._mark_models_from_r2(model_dir)
self.assertTrue(self.worker._models_from_r2(model_dir))
payload = json.loads(discovery.read_text(encoding="utf-8"))
self.assertEqual(payload["port"], 1)
payload = json.loads(runtime_state.read_text(encoding="utf-8"))
self.assertEqual(payload["keep"], "value")
self.assertTrue(payload["models_from_r2"])
finally:
shutil.rmtree(root, ignore_errors=True)