Improve dashboard to fetch data async from screen refreshes

This commit is contained in:
Brett Williams
2022-10-30 23:59:58 -07:00
parent a71e3fe119
commit a36f6d3128

View File

@@ -32,7 +32,7 @@ status_colors = {RenderStatus.ERROR: "red", RenderStatus.CANCELLED: 'orange1', R
categories = [RenderStatus.RUNNING, RenderStatus.ERROR, RenderStatus.NOT_STARTED, RenderStatus.SCHEDULED, categories = [RenderStatus.RUNNING, RenderStatus.ERROR, RenderStatus.NOT_STARTED, RenderStatus.SCHEDULED,
RenderStatus.COMPLETED, RenderStatus.CANCELLED] RenderStatus.COMPLETED, RenderStatus.CANCELLED]
renderer_colors = {'ffmpeg': '[magenta]', 'Blender': '[orange1]', 'aerender': '[purple]'} renderer_colors = {'ffmpeg': '[magenta]', 'blender': '[orange1]', 'aerender': '[purple]'}
local_hostname = socket.gethostname() local_hostname = socket.gethostname()
@@ -132,7 +132,21 @@ def create_jobs_table(all_server_data) -> Table:
if job_status == RenderStatus.ERROR and job['worker']['errors']: if job_status == RenderStatus.ERROR and job['worker']['errors']:
job_text = job_text + "\n" + "\n".join(job['worker']['errors']) job_text = job_text + "\n" + "\n".join(job['worker']['errors'])
elapsed_time = job['worker'].get('time_elapsed', 'unknown') # calculate elapsed time
elapsed_time = 'Unknown'
start_time = None
end_time = None
if job['worker']['start_time']:
start_time = datetime.datetime.fromisoformat(job['worker']['start_time'])
if job['worker']['end_time']:
end_time = datetime.datetime.fromisoformat(job['worker']['end_time'])
if start_time:
if end_time:
elapsed_time = str(end_time - start_time)
elif job_status == RenderStatus.RUNNING:
elapsed_time = str(datetime.datetime.now() - start_time)
# Project name # Project name
project_name = job_color + job['name'] project_name = job_color + job['name']
@@ -174,20 +188,21 @@ def create_status_panel(all_server_data):
return "no status" return "no status"
class RenderDashboard: class RenderServerProxy:
def __init__(self, server_ip=None, server_port="8080"): def __init__(self, server_ip=None, server_port="8080"):
self.server_ip = server_ip self.hostname = server_ip
self.server_port = server_port self.port = server_port
self.local_hostname = local_hostname self.local_hostname = local_hostname
self.fetched_status_data = None
def connect(self): def connect(self):
status = self.request_data('status') status = self.request_data('status')
return status return status
def request_data(self, payload, timeout=2): def request_data(self, payload, timeout=5):
try: try:
req = requests.get(f'http://{self.server_ip}:{self.server_port}/{payload}', timeout=timeout) req = requests.get(f'http://{self.hostname}:{self.port}/{payload}', timeout=timeout)
if req.ok: if req.ok:
return req.json() return req.json()
except Exception as e: except Exception as e:
@@ -204,8 +219,8 @@ class RenderDashboard:
sorted_jobs.extend(found_jobs) sorted_jobs.extend(found_jobs)
return sorted_jobs return sorted_jobs
def get_data(self): def get_data(self, timeout=5):
all_data = self.request_data('full_status', timeout=5) all_data = self.request_data('full_status', timeout=timeout)
return all_data return all_data
@@ -230,23 +245,23 @@ if __name__ == '__main__':
get_server_ip = input("Enter server IP or None for local: ") or local_hostname get_server_ip = input("Enter server IP or None for local: ") or local_hostname
client = RenderDashboard(get_server_ip, "8080") server_proxy = RenderServerProxy(get_server_ip, "8080")
if not client.connect(): if not server_proxy.connect():
if client.server_ip == local_hostname: if server_proxy.hostname == local_hostname:
start_server_input = input("Local server not running. Start server? (y/n) ") start_server_input = input("Local server not running. Start server? (y/n) ")
if start_server_input and start_server_input[0].lower() == "y": if start_server_input and start_server_input[0].lower() == "y":
# Startup the local server # Startup the local server
start_server(background_thread=True) start_server(background_thread=True)
test = client.connect() test = server_proxy.connect()
print(f"connected? {test}") print(f"connected? {test}")
else: else:
print(f"\nUnable to connect to server: {client.server_ip}") print(f"\nUnable to connect to server: {server_proxy.hostname}")
print("\nVerify IP address is correct and server is running") print("\nVerify IP address is correct and server is running")
exit(1) exit(1)
# start the Keyboard thread # start the Keyboard thread
kthread = KeyboardThread(my_callback) # kthread = KeyboardThread(my_callback)
# Console Layout # Console Layout
console = Console() console = Console()
@@ -268,34 +283,42 @@ if __name__ == '__main__':
# Server connection header # Server connection header
header_text = Text(f"Connected to server: ") header_text = Text(f"Connected to server: ")
header_text.append(f"{client.server_ip} ", style="green") header_text.append(f"{server_proxy.hostname} ", style="green")
if client.server_ip == local_hostname: if server_proxy.hostname == local_hostname:
header_text.append("(This Computer)", style="yellow") header_text.append("(This Computer)", style="yellow")
else: else:
header_text.append("(Remote)", style="magenta") header_text.append("(Remote)", style="magenta")
with Live(console=console, screen=False, refresh_per_second=1, transient=True) as live: # background process to update server data independent of the UI
def fetch_server_data(server):
cached_server_data = None
while True: while True:
server_data = client.get_data() fetched_data = server.get_data(timeout=5)
if server_data: if fetched_data:
cached_server_data = server_data server.fetched_status_data = fetched_data
server_data['online'] = True time.sleep(1)
else:
server_data = cached_server_data
if server_data:
server_data['online'] = False
x = threading.Thread(target=fetch_server_data, args=(server_proxy,))
x.daemon = True
x.start()
# draw and update the UI
with Live(console=console, screen=False, refresh_per_second=1, transient=True) as live:
while True:
try: try:
if server_data: if server_proxy.fetched_status_data:
layout["body"].update(create_jobs_table(server_data))
layout["side_top"].update(Panel(create_node_tree(server_data)))
layout["side_bottom"].update(Panel(create_status_panel(server_data)))
online_text = "Online" if server_data['online'] else "Offline" server_online = False
online_color = "green" if server_data['online'] else "red" if server_proxy.fetched_status_data.get('timestamp', None):
timestamp = datetime.datetime.fromisoformat(server_proxy.fetched_status_data['timestamp'])
time_diff = datetime.datetime.now() - timestamp
server_online = time_diff.seconds < 10 # client is offline if not updated in certain time
layout["body"].update(create_jobs_table(server_proxy.fetched_status_data))
layout["side_top"].update(Panel(create_node_tree(server_proxy.fetched_status_data)))
layout["side_bottom"].update(Panel(create_status_panel(server_proxy.fetched_status_data)))
online_text = "Online" if server_online else "Offline"
online_color = "green" if server_online else "red"
layout["header"].update(Panel(Text(f"Zordon Render Client - Version 0.0.1 alpha - {online_text}", layout["header"].update(Panel(Text(f"Zordon Render Client - Version 0.0.1 alpha - {online_text}",
justify="center", style=online_color))) justify="center", style=online_color)))
live.update(layout, refresh=False) live.update(layout, refresh=False)