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,
RenderStatus.COMPLETED, RenderStatus.CANCELLED]
renderer_colors = {'ffmpeg': '[magenta]', 'Blender': '[orange1]', 'aerender': '[purple]'}
renderer_colors = {'ffmpeg': '[magenta]', 'blender': '[orange1]', 'aerender': '[purple]'}
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']:
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 = job_color + job['name']
@@ -174,20 +188,21 @@ def create_status_panel(all_server_data):
return "no status"
class RenderDashboard:
class RenderServerProxy:
def __init__(self, server_ip=None, server_port="8080"):
self.server_ip = server_ip
self.server_port = server_port
self.hostname = server_ip
self.port = server_port
self.local_hostname = local_hostname
self.fetched_status_data = None
def connect(self):
status = self.request_data('status')
return status
def request_data(self, payload, timeout=2):
def request_data(self, payload, timeout=5):
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:
return req.json()
except Exception as e:
@@ -204,8 +219,8 @@ class RenderDashboard:
sorted_jobs.extend(found_jobs)
return sorted_jobs
def get_data(self):
all_data = self.request_data('full_status', timeout=5)
def get_data(self, timeout=5):
all_data = self.request_data('full_status', timeout=timeout)
return all_data
@@ -230,23 +245,23 @@ if __name__ == '__main__':
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 client.server_ip == local_hostname:
if not server_proxy.connect():
if server_proxy.hostname == local_hostname:
start_server_input = input("Local server not running. Start server? (y/n) ")
if start_server_input and start_server_input[0].lower() == "y":
# Startup the local server
start_server(background_thread=True)
test = client.connect()
test = server_proxy.connect()
print(f"connected? {test}")
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")
exit(1)
# start the Keyboard thread
kthread = KeyboardThread(my_callback)
# kthread = KeyboardThread(my_callback)
# Console Layout
console = Console()
@@ -268,34 +283,42 @@ if __name__ == '__main__':
# Server connection header
header_text = Text(f"Connected to server: ")
header_text.append(f"{client.server_ip} ", style="green")
if client.server_ip == local_hostname:
header_text.append(f"{server_proxy.hostname} ", style="green")
if server_proxy.hostname == local_hostname:
header_text.append("(This Computer)", style="yellow")
else:
header_text.append("(Remote)", style="magenta")
with Live(console=console, screen=False, refresh_per_second=1, transient=True) as live:
cached_server_data = None
# background process to update server data independent of the UI
def fetch_server_data(server):
while True:
server_data = client.get_data()
if server_data:
cached_server_data = server_data
server_data['online'] = True
else:
server_data = cached_server_data
if server_data:
server_data['online'] = False
fetched_data = server.get_data(timeout=5)
if fetched_data:
server.fetched_status_data = fetched_data
time.sleep(1)
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:
if server_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)))
if server_proxy.fetched_status_data:
online_text = "Online" if server_data['online'] else "Offline"
online_color = "green" if server_data['online'] else "red"
server_online = False
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}",
justify="center", style=online_color)))
live.update(layout, refresh=False)