Skip to content

Commit 8ed9e2c

Browse files
change api for calibrations
1 parent 4c30aa5 commit 8ed9e2c

File tree

3 files changed

+73
-59
lines changed

3 files changed

+73
-59
lines changed

pioreactorui/api.py

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ def update_job_on_unit(pioreactor_unit: str, experiment: str, job: str) -> Respo
278278
return Response(status=202)
279279

280280

281-
@api.route("/workers/<pioreactor_unit>/system/reboot", methods=["POST"])
281+
@api.route("/units/<pioreactor_unit>/system/reboot", methods=["POST"])
282282
def reboot_unit(pioreactor_unit: str) -> ResponseReturnValue:
283283
"""Reboots unit"""
284284
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
@@ -288,7 +288,7 @@ def reboot_unit(pioreactor_unit: str) -> ResponseReturnValue:
288288
return create_task_response(task)
289289

290290

291-
@api.route("/workers/<pioreactor_unit>/system/shutdown", methods=["POST"])
291+
@api.route("/units/<pioreactor_unit>/system/shutdown", methods=["POST"])
292292
def shutdown_unit(pioreactor_unit: str) -> ResponseReturnValue:
293293
"""Shutdown unit"""
294294
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
@@ -428,7 +428,7 @@ def get_recent_logs_for_unit_and_experiment(
428428
return jsonify(recent_logs)
429429

430430

431-
@api.route("/units/<pioreactor_unit>/experiments/<experiment>/logs", methods=["GET"])
431+
@api.route("/workers/<pioreactor_unit>/experiments/<experiment>/logs", methods=["GET"])
432432
def get_logs_for_unit_and_experiment(pioreactor_unit: str, experiment: str) -> ResponseReturnValue:
433433
"""Shows event logs from all units, uses pagination."""
434434

@@ -477,7 +477,7 @@ def get_logs_for_unit(pioreactor_unit: str) -> ResponseReturnValue:
477477
return jsonify(recent_logs)
478478

479479

480-
@api.route("/units/<pioreactor_unit>/experiments/<experiment>/logs", methods=["POST"])
480+
@api.route("/workers/<pioreactor_unit>/experiments/<experiment>/logs", methods=["POST"])
481481
def publish_new_log(pioreactor_unit: str, experiment: str) -> ResponseReturnValue:
482482
body = request.get_json()
483483

@@ -711,50 +711,46 @@ def get_all_calibrations(pioreactor_unit) -> ResponseReturnValue:
711711
return create_task_response(task)
712712

713713

714-
@api.route("/workers/<pioreactor_unit>/calibrations/<cal_type>", methods=["GET"])
715-
def get_calibrations(pioreactor_unit, cal_type) -> ResponseReturnValue:
714+
@api.route("/workers/<pioreactor_unit>/calibrations/<device>", methods=["GET"])
715+
def get_calibrations(pioreactor_unit, device) -> ResponseReturnValue:
716716
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
717-
task = broadcast_get_across_cluster(f"/unit_api/calibrations/{cal_type}")
717+
task = broadcast_get_across_cluster(f"/unit_api/calibrations/{device}")
718718
else:
719719
task = tasks.multicast_get_across_cluster(
720-
f"/unit_api/calibrations/{cal_type}", [pioreactor_unit]
720+
f"/unit_api/calibrations/{device}", [pioreactor_unit]
721721
)
722722
return create_task_response(task)
723723

724724

725-
@api.route(
726-
"/workers/<pioreactor_unit>/calibrations/<cal_type>/<cal_name>/active", methods=["PATCH"]
727-
)
728-
def set_active_calibration(pioreactor_unit, cal_type, cal_name) -> ResponseReturnValue:
725+
@api.route("/workers/<pioreactor_unit>/calibrations/<device>/<cal_name>/active", methods=["PATCH"])
726+
def set_active_calibration(pioreactor_unit, device, cal_name) -> ResponseReturnValue:
729727
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
730-
task = broadcast_patch_across_cluster(
731-
f"/unit_api/calibrations/{cal_type}/{cal_name}/active"
732-
)
728+
task = broadcast_patch_across_cluster(f"/unit_api/calibrations/{device}/{cal_name}/active")
733729
else:
734730
task = tasks.multicast_patch_across_cluster(
735-
f"/unit_api/calibrations/{cal_type}/{cal_name}/active", [pioreactor_unit]
731+
f"/unit_api/calibrations/{device}/{cal_name}/active", [pioreactor_unit]
736732
)
737733
return create_task_response(task)
738734

739735

740-
@api.route("/workers/<pioreactor_unit>/calibrations/<cal_type>/active", methods=["DELETE"])
741-
def remove_active_status_calibration(pioreactor_unit, cal_type) -> ResponseReturnValue:
736+
@api.route("/workers/<pioreactor_unit>/calibrations/<device>/active", methods=["DELETE"])
737+
def remove_active_status_calibration(pioreactor_unit, device) -> ResponseReturnValue:
742738
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
743-
task = broadcast_delete_across_cluster(f"/unit_api/calibrations/{cal_type}/active")
739+
task = broadcast_delete_across_cluster(f"/unit_api/calibrations/{device}/active")
744740
else:
745741
task = tasks.multicast_delete_across_cluster(
746-
f"/unit_api/calibrations/{cal_type}/active", [pioreactor_unit]
742+
f"/unit_api/calibrations/{device}/active", [pioreactor_unit]
747743
)
748744
return create_task_response(task)
749745

750746

751-
@api.route("/workers/<pioreactor_unit>/calibrations/<cal_type>/<cal_name>", methods=["DELETE"])
752-
def remove_calibration(pioreactor_unit, cal_type, cal_name) -> ResponseReturnValue:
747+
@api.route("/workers/<pioreactor_unit>/calibrations/<device>/<cal_name>", methods=["DELETE"])
748+
def remove_calibration(pioreactor_unit, device, cal_name) -> ResponseReturnValue:
753749
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
754-
task = broadcast_delete_across_cluster(f"/unit_api/calibrations/{cal_type}/{cal_name}")
750+
task = broadcast_delete_across_cluster(f"/unit_api/calibrations/{device}/{cal_name}")
755751
else:
756752
task = tasks.multicast_delete_across_cluster(
757-
f"/unit_api/calibrations/{cal_type}/{cal_name}", [pioreactor_unit]
753+
f"/unit_api/calibrations/{device}/{cal_name}", [pioreactor_unit]
758754
)
759755
return create_task_response(task)
760756

@@ -809,12 +805,17 @@ def uninstall_plugin_across_cluster(pioreactor_unit: str) -> ResponseReturnValue
809805
)
810806

811807

812-
@api.route("/jobs/running", methods=["GET"])
813-
def get_jobs_running_across_cluster() -> ResponseReturnValue:
814-
return create_task_response(broadcast_get_across_cluster("/unit_api/jobs/running"))
808+
@api.route("/units/<pioreactor_unit>/jobs/running", methods=["GET"])
809+
def get_jobs_running(pioreactor_unit: str) -> ResponseReturnValue:
810+
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
811+
return create_task_response(broadcast_get_across_cluster("/unit_api/jobs/running"))
812+
else:
813+
return create_task_response(
814+
tasks.multicast_get_across_cluster("/unit_api/jobs/running", [pioreactor_unit])
815+
)
815816

816817

817-
@api.route("/jobs/running/experiments/<experiment>", methods=["GET"])
818+
@api.route("/experiments/<experiment>/jobs/running", methods=["GET"])
818819
def get_jobs_running_across_cluster_in_experiment(experiment) -> ResponseReturnValue:
819820
list_of_assigned_workers = get_all_workers_in_experiment(experiment)
820821

@@ -852,7 +853,7 @@ def get_setting_for_job_across_cluster_in_experiment(
852853

853854

854855
@api.route("/workers/<pioreactor_unit>/jobs/settings/job_name/<job_name>", methods=["GET"])
855-
def get_job_settings_for_worker(pioreactor_unit, job_name) -> ResponseReturnValue:
856+
def get_job_settings_for_worker(pioreactor_unit: str, job_name: str) -> ResponseReturnValue:
856857
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
857858
task = broadcast_get_across_cluster(f"/unit_api/jobs/settings/job_name/{job_name}")
858859
else:
@@ -866,7 +867,9 @@ def get_job_settings_for_worker(pioreactor_unit, job_name) -> ResponseReturnValu
866867
"/workers/<pioreactor_unit>/jobs/settings/job_name/<job_name>/setting/<setting>",
867868
methods=["GET"],
868869
)
869-
def get_job_setting_for_worker(pioreactor_unit, job_name, setting) -> ResponseReturnValue:
870+
def get_job_setting_for_worker(
871+
pioreactor_unit: str, job_name: str, setting: str
872+
) -> ResponseReturnValue:
870873
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
871874
task = broadcast_get_across_cluster(
872875
f"/unit_api/jobs/settings/job_name/{job_name}/setting/{setting}"
@@ -881,14 +884,24 @@ def get_job_setting_for_worker(pioreactor_unit, job_name, setting) -> ResponseRe
881884
## MISC
882885

883886

884-
@api.route("/versions/app", methods=["GET"])
885-
def get_app_versions_across_cluster() -> ResponseReturnValue:
886-
return create_task_response(broadcast_get_across_cluster("/unit_api/versions/app"))
887+
@api.route("/units/<pioreactor_unit>/versions/app", methods=["GET"])
888+
def get_app_versions(pioreactor_unit: str) -> ResponseReturnValue:
889+
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
890+
return broadcast_get_across_cluster("/unit_api/versions/app")
891+
else:
892+
return create_task_response(
893+
tasks.multicast_get_across_cluster("/unit_api/versions/app", [pioreactor_unit])
894+
)
887895

888896

889-
@api.route("/versions/ui", methods=["GET"])
890-
def get_ui_versions_across_cluster() -> ResponseReturnValue:
891-
return create_task_response(broadcast_get_across_cluster("/unit_api/versions/ui"))
897+
@api.route("/units/<pioreactor_unit>/versions/ui", methods=["GET"])
898+
def get_ui_versions_across_cluster(pioreactor_unit: str) -> ResponseReturnValue:
899+
if pioreactor_unit == UNIVERSAL_IDENTIFIER:
900+
return broadcast_get_across_cluster("/unit_api/versions/ui")
901+
else:
902+
return create_task_response(
903+
tasks.multicast_get_across_cluster("/unit_api/versions/ui", [pioreactor_unit])
904+
)
892905

893906

894907
## UPLOADS
@@ -1942,7 +1955,7 @@ def get_list_of_workers_for_experiment(experiment: str) -> ResponseReturnValue:
19421955
return jsonify(workers)
19431956

19441957

1945-
@api.route("/experiments/<experiment>/historical_workers", methods=["GET"])
1958+
@api.route("/experiments/<experiment>/historical_worker_assignments", methods=["GET"])
19461959
def get_list_of_historical_workers_for_experiment(experiment: str) -> ResponseReturnValue:
19471960
workers = query_app_db(
19481961
"""

pioreactorui/tasks.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from msgspec import DecodeError
1717
from pioreactor.config import config
1818
from pioreactor.mureq import HTTPErrorStatus
19+
from pioreactor.mureq import HTTPException
1920
from pioreactor.pubsub import delete_from
2021
from pioreactor.pubsub import get_from
2122
from pioreactor.pubsub import patch_into
@@ -303,7 +304,7 @@ def post_to_worker(worker: str, endpoint: str, json: dict | None = None) -> tupl
303304
r = post_into(resolve_to_address(worker), endpoint, json=json, timeout=1)
304305
r.raise_for_status()
305306
return worker, r.json()
306-
except HTTPErrorStatus as e:
307+
except (HTTPErrorStatus, HTTPException) as e:
307308
logger.error(
308309
f"Could not post to {worker}'s {endpoint=}, sent {json=} and returned {e}. Check connection?"
309310
)
@@ -335,7 +336,7 @@ def get_from_worker(
335336
r = get_from(resolve_to_address(worker), endpoint, json=json, timeout=timeout)
336337
r.raise_for_status()
337338
return worker, r.json()
338-
except HTTPErrorStatus as e:
339+
except (HTTPErrorStatus, HTTPException) as e:
339340
logger.error(
340341
f"Could not get from {worker}'s {endpoint=}, sent {json=} and returned {e}. Check connection?"
341342
)
@@ -365,7 +366,7 @@ def patch_to_worker(worker: str, endpoint: str, json: dict | None = None) -> tup
365366
r = patch_into(resolve_to_address(worker), endpoint, json=json, timeout=1)
366367
r.raise_for_status()
367368
return worker, r.json()
368-
except HTTPErrorStatus as e:
369+
except (HTTPErrorStatus, HTTPException) as e:
369370
logger.error(
370371
f"Could not PATCH to {worker}'s {endpoint=}, sent {json=} and returned {e}. Check connection?"
371372
)
@@ -395,7 +396,7 @@ def delete_from_worker(worker: str, endpoint: str, json: dict | None = None) ->
395396
r = delete_from(resolve_to_address(worker), endpoint, json=json, timeout=1)
396397
r.raise_for_status()
397398
return worker, r.json() if r.content else None
398-
except HTTPErrorStatus as e:
399+
except (HTTPErrorStatus, HTTPException) as e:
399400
logger.error(
400401
f"Could not DELETE {worker}'s {endpoint=}, sent {json=} and returned {e}. Check connection?"
401402
)

pioreactorui/unit_api.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -548,21 +548,21 @@ def get_all_calibrations() -> ResponseReturnValue:
548548
for file in calibration_dir.glob("*/*.yaml"):
549549
try:
550550
cal = yaml_decode(file.read_bytes())
551-
cal_type = cal["calibration_type"]
552-
cal["is_active"] = cache.get(cal_type) == cal["calibration_name"]
553-
if cal_type in all_calibrations:
554-
all_calibrations[cal_type].append(cal)
551+
device = cal["device"]
552+
cal["is_active"] = cache.get(device) == cal["calibration_name"]
553+
if device in all_calibrations:
554+
all_calibrations[device].append(cal)
555555
else:
556-
all_calibrations[cal_type] = [cal]
556+
all_calibrations[device] = [cal]
557557
except Exception as e:
558558
print(f"Error reading {file.stem}: {e}")
559559

560560
return attach_cache_control(jsonify(all_calibrations), max_age=10)
561561

562562

563-
@unit_api.route("/calibrations/<cal_type>", methods=["GET"])
564-
def get_calibrations(cal_type) -> ResponseReturnValue:
565-
calibration_dir = Path(f"{env['DOT_PIOREACTOR']}/storage/calibrations/{cal_type}")
563+
@unit_api.route("/calibrations/<device>", methods=["GET"])
564+
def get_calibrations_by_device(device) -> ResponseReturnValue:
565+
calibration_dir = Path(f"{env['DOT_PIOREACTOR']}/storage/calibrations/{device}")
566566

567567
if not calibration_dir.exists():
568568
abort(404)
@@ -573,33 +573,33 @@ def get_calibrations(cal_type) -> ResponseReturnValue:
573573
for file in calibration_dir.glob("*.yaml"):
574574
try:
575575
cal = yaml_decode(file.read_bytes())
576-
cal["is_active"] = c.get(cal_type) == cal["calibration_name"]
576+
cal["is_active"] = c.get(device) == cal["calibration_name"]
577577
calibrations.append(cal)
578578
except Exception as e:
579579
print(f"Error reading {file.stem}: {e}")
580580

581581
return attach_cache_control(jsonify(calibrations), max_age=10)
582582

583583

584-
@unit_api.route("/calibrations/<cal_type>/<cal_name>/active", methods=["PATCH"])
585-
def set_active_calibration(cal_type, cal_name) -> ResponseReturnValue:
584+
@unit_api.route("/calibrations/<device>/<cal_name>/active", methods=["PATCH"])
585+
def set_active_calibration(device, cal_name) -> ResponseReturnValue:
586586
with local_persistent_storage("active_calibrations") as c:
587-
c[cal_type] = cal_name
587+
c[device] = cal_name
588588

589589
return Response(status=200)
590590

591591

592-
@unit_api.route("/calibrations/<cal_type>/active", methods=["DELETE"])
593-
def remove_active_status_calibration(cal_type) -> ResponseReturnValue:
592+
@unit_api.route("/calibrations/<device>/active", methods=["DELETE"])
593+
def remove_active_status_calibration(device) -> ResponseReturnValue:
594594
with local_persistent_storage("active_calibrations") as c:
595-
c.pop(cal_type)
595+
c.pop(device)
596596

597597
return Response(status=200)
598598

599599

600-
@unit_api.route("/calibrations/<cal_type>/<cal_name>", methods=["DELETE"])
601-
def remove_calibration(cal_type, cal_name) -> ResponseReturnValue:
602-
target_file = CALIBRATION_PATH / cal_type / f"{cal_name}.yaml"
600+
@unit_api.route("/calibrations/<device>/<cal_name>", methods=["DELETE"])
601+
def remove_calibration(device, cal_name) -> ResponseReturnValue:
602+
target_file = CALIBRATION_PATH / device / f"{cal_name}.yaml"
603603
if not target_file.exists():
604604
abort(404, f"{target_file} not found")
605605

0 commit comments

Comments
 (0)