Register runner when starting script
Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
Supervisor flow demo for HeroCoordinator.
|
||||
|
||||
This script:
|
||||
- Optionally pre-registers a Python runner on the target Supervisor over Mycelium using an admin secret (--admin-secret). If the flag is not set, this step is skipped.
|
||||
- Creates an actor
|
||||
- Creates a context granting the actor admin/reader/executor privileges
|
||||
- Registers a Runner in the context targeting a Supervisor reachable via Mycelium (by public key or IP)
|
||||
@@ -20,10 +21,13 @@ Notes:
|
||||
- Exactly one of --dst-ip or --dst-pk must be provided.
|
||||
- Runner.topic defaults to "supervisor.rpc" (see main.rs).
|
||||
- The router auto-discovers contexts and will deliver job.run messages to the supervisor.
|
||||
- Mycelium URL is read from MYCELIUM_URL (default http://127.0.0.1:8990).
|
||||
- supervisor.register_runner uses static name="python" and queue="python".
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import base64
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
@@ -36,6 +40,9 @@ JSONRPC_VERSION = "2.0"
|
||||
def env_url() -> str:
|
||||
return os.getenv("COORDINATOR_URL", "http://127.0.0.1:9652").rstrip("/")
|
||||
|
||||
def env_mycelium_url() -> str:
|
||||
return os.getenv("MYCELIUM_URL", "http://127.0.0.1:8990").rstrip("/")
|
||||
|
||||
|
||||
class JsonRpcClient:
|
||||
def __init__(self, url: str):
|
||||
@@ -87,6 +94,60 @@ def print_header(title: str):
|
||||
def pretty(obj: Any):
|
||||
print(json.dumps(obj, indent=2, sort_keys=True))
|
||||
|
||||
def mycelium_register_runner(
|
||||
myc: "JsonRpcClient",
|
||||
dst_pk: Optional[str],
|
||||
dst_ip: Optional[str],
|
||||
topic: str,
|
||||
admin_secret: str,
|
||||
name: str = "python",
|
||||
queue: str = "python",
|
||||
timeout: int = 15,
|
||||
) -> Any:
|
||||
"""
|
||||
Send supervisor.register_runner over Mycelium using pushMessage and wait for the reply.
|
||||
- myc: JsonRpcClient for the Mycelium API (MYCELIUM_URL)
|
||||
- dst_pk/dst_ip: destination on the overlay; one of them must be provided
|
||||
- topic: message topic (defaults to supervisor.rpc from args)
|
||||
- admin_secret: supervisor admin secret to authorize the registration
|
||||
- name/queue: static identifiers for the python runner on the supervisor
|
||||
- timeout: seconds to wait for a reply
|
||||
Returns the JSON-RPC 'result' from the supervisor or raises on error/timeout.
|
||||
"""
|
||||
envelope = {
|
||||
"jsonrpc": JSONRPC_VERSION,
|
||||
"id": 1,
|
||||
"method": "register_runner",
|
||||
"params": [{"secret": admin_secret, "name": name, "queue": queue}],
|
||||
}
|
||||
payload_b64 = base64.b64encode(json.dumps(envelope).encode("utf-8")).decode("ascii")
|
||||
topic_b64 = base64.b64encode(topic.encode("utf-8")).decode("ascii")
|
||||
|
||||
if dst_pk:
|
||||
dst = {"pk": dst_pk}
|
||||
elif dst_ip:
|
||||
dst = {"ip": dst_ip}
|
||||
else:
|
||||
raise RuntimeError("Either dst_pk or dst_ip must be provided for Mycelium destination")
|
||||
|
||||
params = {
|
||||
"message": {"dst": dst, "topic": topic_b64, "payload": payload_b64},
|
||||
}
|
||||
resp = myc.call("pushMessage", params)
|
||||
time.sleep(15)
|
||||
|
||||
# Expect an InboundMessage with a payload if a reply was received
|
||||
# if isinstance(resp, dict) and "payload" in resp:
|
||||
# try:
|
||||
# reply = json.loads(base64.b64decode(resp["payload"]).decode("utf-8"))
|
||||
# except Exception as e:
|
||||
# raise RuntimeError(f"Invalid supervisor reply payload: {e}")
|
||||
# if isinstance(reply, dict) and reply.get("error"):
|
||||
# raise RuntimeError(f"Supervisor register_runner error: {json.dumps(reply['error'])}")
|
||||
# return reply.get("result")
|
||||
#
|
||||
# raise RuntimeError("No reply received from supervisor for register_runner (timeout)")
|
||||
|
||||
|
||||
def try_create_or_load(client: JsonRpcClient, create_method: str, create_params: Dict[str, Any],
|
||||
load_method: str, load_params: Dict[str, Any]) -> Any:
|
||||
@@ -124,6 +185,7 @@ def parse_args() -> argparse.Namespace:
|
||||
)
|
||||
p.add_argument("--topic", default="supervisor.rpc", help="Supervisor topic. Default: supervisor.rpc")
|
||||
p.add_argument("--secret", help="Optional supervisor secret used for authenticated supervisor calls")
|
||||
p.add_argument("--admin-secret", help="Supervisor admin secret to pre-register a Python runner over Mycelium. If omitted, pre-registration is skipped.")
|
||||
p.add_argument("--poll-interval", type=float, default=2.0, help="Flow poll interval seconds. Default: 2.0")
|
||||
p.add_argument("--poll-timeout", type=int, default=600, help="Max seconds to wait for flow completion. Default: 600")
|
||||
return p.parse_args()
|
||||
@@ -138,6 +200,9 @@ def main():
|
||||
url = env_url()
|
||||
client = JsonRpcClient(url)
|
||||
|
||||
mycelium_url = env_mycelium_url()
|
||||
mycelium_client = JsonRpcClient(mycelium_url) if getattr(args, "admin_secret", None) else None
|
||||
|
||||
actor_id = int(args.actor_id)
|
||||
context_id = int(args.context_id)
|
||||
runner_id = int(args.runner_id)
|
||||
@@ -189,6 +254,25 @@ def main():
|
||||
runner_pubkey = args.dst_pk if args.dst_pk else ""
|
||||
runner_address = args.dst_ip if args.dst_ip else "127.0.0.1"
|
||||
|
||||
# Optional: pre-register a Python runner on the Supervisor over Mycelium using an admin secret
|
||||
if getattr(args, "admin_secret", None):
|
||||
print_header("supervisor.register_runner (pre-register via Mycelium)")
|
||||
try:
|
||||
mycelium_result = mycelium_register_runner(
|
||||
mycelium_client,
|
||||
args.dst_pk if args.dst_pk else None,
|
||||
args.dst_ip if args.dst_ip else None,
|
||||
topic,
|
||||
args.admin_secret,
|
||||
name="Python",
|
||||
queue="Python",
|
||||
timeout=15,
|
||||
)
|
||||
print("Supervisor register_runner ->", mycelium_result)
|
||||
except Exception as e:
|
||||
print(f"ERROR: Supervisor pre-registration failed: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print_header("runner.create (or load)")
|
||||
# runner.load requires both context_id and id
|
||||
try:
|
||||
@@ -351,4 +435,4 @@ if __name__ == "__main__":
|
||||
except Exception as e:
|
||||
print_header("Error")
|
||||
print(str(e))
|
||||
sys.exit(1)
|
||||
sys.exit(1)
|
||||
|
Reference in New Issue
Block a user