Refactor: DistributedJobManager with pub/sub status change notifications (#25)

* Add pubsub to render_queue and base_worker

* Refactor: Convert ZeroconfServer to Singleton with Class Methods

* New API for subjob servers to notify parent job servers of status changes

* Refactor: Move all subjob related methods to distributed_job_manager.py

* Rewrite for wait_for_subjobs

* Fix: DistributedJobManager.find_available_servers() takes 1 positional argument but 3 were given

* DistributedJobManager should now notify / be notified abotu background job changes

* Fix the make_ready api. Change children keyname to be id@hostname so it can be unique

* Fixes

* Image sequence to movie needs to find the actual start frame

* Fix: subjob_status_change did not return a valid response

* Fix client renderer selection

* Small fix for subjob status checking

* Fix issue with divide_frames_equally

* Fix issue where downloads were not occurring

* Fix issue where old status was being reported

* Add docstrings and code cleanup
This commit is contained in:
2023-06-30 19:49:57 -05:00
committed by GitHub
parent 0b0b410e76
commit 34fbdaa4d9
12 changed files with 503 additions and 255 deletions

View File

@@ -86,3 +86,20 @@ def get_time_elapsed(start_time=None, end_time=None):
elapsed_time_string = strfdelta(elapsed_time) if elapsed_time else None
return elapsed_time_string
def get_file_size_human(file_path):
size_in_bytes = os.path.getsize(file_path)
# Convert size to a human readable format
if size_in_bytes < 1024:
return f"{size_in_bytes} B"
elif size_in_bytes < 1024 ** 2:
return f"{size_in_bytes / 1024:.2f} KB"
elif size_in_bytes < 1024 ** 3:
return f"{size_in_bytes / 1024 ** 2:.2f} MB"
elif size_in_bytes < 1024 ** 4:
return f"{size_in_bytes / 1024 ** 3:.2f} GB"
else:
return f"{size_in_bytes / 1024 ** 4:.2f} TB"

View File

@@ -49,75 +49,3 @@ def generate_thumbnail_for_job(job, thumb_video_path, thumb_image_path, max_widt
if video_files and not os.path.exists(thumb_video_path):
x = threading.Thread(target=generate_thumb_thread, args=(video_files[0],))
x.start()
def divide_frames_evenly(start_frame, end_frame, num_servers):
frame_range = end_frame - start_frame + 1
frames_per_server = frame_range // num_servers
leftover_frames = frame_range % num_servers
ranges = []
current_start = start_frame
for i in range(num_servers):
current_end = current_start + frames_per_server - 1
if leftover_frames > 0:
current_end += 1
leftover_frames -= 1
if current_start <= current_end:
ranges.append((current_start, current_end))
current_start = current_end + 1
return ranges
def divide_frames_by_cpu_count(frame_start, frame_end, servers):
total_frames = frame_end - frame_start + 1
total_performance = sum(server['cpu_count'] for server in servers)
frame_ranges = {}
current_frame = frame_start
allocated_frames = 0
for i, server in enumerate(servers):
if i == len(servers) - 1: # if it's the last server
# Give all remaining frames to the last server
num_frames = total_frames - allocated_frames
else:
num_frames = round((server['cpu_count'] / total_performance) * total_frames)
allocated_frames += num_frames
frame_end_for_server = current_frame + num_frames - 1
if current_frame <= frame_end_for_server:
frame_ranges[server['hostname']] = (current_frame, frame_end_for_server)
current_frame = frame_end_for_server + 1
return frame_ranges
def find_available_servers(server_list, renderer, start_frame, end_frame):
local_hostname = socket.gethostname()
subjob_servers = [{'hostname': local_hostname, 'cpu_count': psutil.cpu_count(logical=False)}]
for hostname in server_list:
if hostname != local_hostname:
response = RenderServerProxy(hostname).get_status()
if response and response.get('renderers', {}).get(renderer, {}).get('is_ready', False):
subjob_servers.append({'hostname': hostname, 'cpu_count': int(response['cpu_count'])})
if len(subjob_servers) == 1:
logger.debug("No available servers to split job with. Skipping subjob creation.")
return subjob_servers
# Calculate respective frames for each server
breakdown = divide_frames_by_cpu_count(start_frame, end_frame, subjob_servers)
subjob_servers = [server for server in subjob_servers if breakdown.get(server['hostname']) is not None]
for server in subjob_servers:
server['frame_range'] = breakdown[server['hostname']]
server['total_frames'] = breakdown[server['hostname']][-1] - breakdown[server['hostname']][0] + 1
return subjob_servers
if __name__ == "__main__":
found_servers = ['kamino.local', 'deathstar.local']
print(find_available_servers(found_servers, 'blender', 1, 5))