Compare commits

..

3 Commits

Author SHA1 Message Date
2182899162 Merge pull request 'reporting campaign status' (#20) from zfp-oss into main
Some checks failed
Build Sphinx Docs Set / Build Docs (push) Successful in 20s
Test with tox / Test with tox (3.12) (push) Successful in 6m44s
Test with tox / Test with tox (3.11) (push) Successful in 7m59s
Build Project / Build Project (3.12) (push) Successful in 12m58s
Build Project / Build Project (3.10) (push) Successful in 13m5s
Build Project / Build Project (3.11) (push) Successful in 13m4s
Test with tox / Test with tox (3.10) (push) Failing after 13m6s
Reviewed-on: #20
2026-04-01 15:25:02 -04:00
ben
da9a0b07bd poetry update
Some checks failed
Build Sphinx Docs Set / Build Docs (pull_request) Successful in 38s
Test with tox / Test with tox (3.11) (pull_request) Failing after 14m19s
Build Project / Build Project (3.10) (pull_request) Successful in 17m2s
Test with tox / Test with tox (3.10) (pull_request) Failing after 17m1s
Build Project / Build Project (3.12) (pull_request) Successful in 17m29s
Build Project / Build Project (3.11) (pull_request) Successful in 17m31s
Test with tox / Test with tox (3.12) (pull_request) Failing after 28m46s
2026-04-01 15:05:30 -04:00
ben
3e9ac43800 reporting campaign status
Some checks failed
Build Sphinx Docs Set / Build Docs (pull_request) Successful in 7m42s
Test with tox / Test with tox (3.10) (pull_request) Failing after 8m9s
Build Project / Build Project (3.10) (pull_request) Successful in 8m22s
Build Project / Build Project (3.11) (pull_request) Successful in 8m21s
Build Project / Build Project (3.12) (pull_request) Successful in 8m21s
Test with tox / Test with tox (3.11) (pull_request) Successful in 8m33s
Test with tox / Test with tox (3.12) (pull_request) Successful in 1m14s
2026-04-01 14:08:13 -04:00
2 changed files with 30 additions and 3 deletions

6
poetry.lock generated
View File

@ -688,14 +688,14 @@ test = ["pytest (>=6)"]
[[package]] [[package]]
name = "fastapi" name = "fastapi"
version = "0.135.2" version = "0.135.3"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false optional = false
python-versions = ">=3.10" python-versions = ">=3.10"
groups = ["server", "test"] groups = ["server", "test"]
files = [ files = [
{file = "fastapi-0.135.2-py3-none-any.whl", hash = "sha256:0af0447d541867e8db2a6a25c23a8c4bd80e2394ac5529bd87501bbb9e240ca5"}, {file = "fastapi-0.135.3-py3-none-any.whl", hash = "sha256:9b0f590c813acd13d0ab43dd8494138eb58e484bfac405db1f3187cfc5810d98"},
{file = "fastapi-0.135.2.tar.gz", hash = "sha256:88a832095359755527b7f63bb4c6bc9edb8329a026189eed83d6c1afcf419d56"}, {file = "fastapi-0.135.3.tar.gz", hash = "sha256:bd6d7caf1a2bdd8d676843cdcd2287729572a1ef524fc4d65c17ae002a1be654"},
] ]
[package.dependencies] [package.dependencies]

View File

@ -226,8 +226,11 @@ class NodeAgent:
result = executor.run() result = executor.run()
logger.info("Campaign %s completed — uploading recordings", campaign_id[:8]) logger.info("Campaign %s completed — uploading recordings", campaign_id[:8])
self._upload_recordings(campaign_id, config, result) self._upload_recordings(campaign_id, config, result)
result_dict = result.to_dict() if hasattr(result, "to_dict") else None
self._report_campaign_status(campaign_id, "completed", result=result_dict)
except Exception as exc: except Exception as exc:
logger.error("Campaign %s failed: %s", campaign_id[:8], exc) logger.error("Campaign %s failed: %s", campaign_id[:8], exc)
self._report_campaign_status(campaign_id, "failed", error=str(exc))
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# Recording upload (chunked for large files) # Recording upload (chunked for large files)
@ -268,6 +271,30 @@ class NodeAgent:
except Exception as exc: except Exception as exc:
logger.warning("Campaign %s: upload of %s failed: %s", campaign_id[:8], filename, exc) logger.warning("Campaign %s: upload of %s failed: %s", campaign_id[:8], filename, exc)
def _report_campaign_status(
self,
campaign_id: str,
status: str,
result: "dict | None" = None,
error: "str | None" = None,
) -> None:
"""POST campaign completion/failure back to the hub so GET /status/{id} resolves."""
payload: dict = {"campaign_id": campaign_id, "status": status}
if result is not None:
payload["result"] = result
if error is not None:
payload["error"] = error
try:
resp = self._post(
f"/orchestrator/nodes/{self.node_id}/campaign-status",
json=payload,
timeout=15,
)
resp.raise_for_status()
logger.info("Campaign %s: reported status=%s to hub", campaign_id[:8], status)
except Exception as exc:
logger.warning("Campaign %s: failed to report status to hub: %s", campaign_id[:8], exc)
def _upload_file(self, base_url: str, file_path: str, metadata: dict) -> dict: def _upload_file(self, base_url: str, file_path: str, metadata: dict) -> dict:
"""Upload *file_path*, choosing chunked or direct path based on file size.""" """Upload *file_path*, choosing chunked or direct path based on file size."""
import requests as _requests import requests as _requests