Tophness2022 commited on
Commit
1ada5a6
·
1 Parent(s): 2217223

clear queue aborts currently generating item

Browse files
Files changed (1) hide show
  1. wgp.py +60 -96
wgp.py CHANGED
@@ -362,24 +362,21 @@ def save_queue_action(state):
362
  gen = get_gen_info(state)
363
  queue = gen.get("queue", [])
364
 
365
- if not queue or len(queue) <=1 : # Check if queue is empty or only has the placeholder
366
  gr.Info("Queue is empty. Nothing to save.")
367
- return None # Return None if nothing to save
368
 
369
- # Use an in-memory buffer for the zip file
370
  zip_buffer = io.BytesIO()
371
 
372
- # Still use a temporary directory *only* for storing images before zipping
373
  with tempfile.TemporaryDirectory() as tmpdir:
374
  queue_manifest = []
375
- image_paths_in_zip = {} # Tracks image PIL object ID -> filename in zip
376
 
377
  for task_index, task in enumerate(queue):
378
- # Skip the placeholder item if it exists
379
  if task is None or not isinstance(task, dict) or task_index == 0: continue
380
 
381
  params_copy = task.get('params', {}).copy()
382
- task_id_s = task.get('id', f"task_{task_index}") # Use a different var name
383
 
384
  image_keys = ["image_start", "image_end", "image_refs"]
385
  for key in image_keys:
@@ -387,95 +384,71 @@ def save_queue_action(state):
387
  if images_pil is None:
388
  continue
389
 
390
- # Ensure images_pil is always a list for processing
391
  is_originally_list = isinstance(images_pil, list)
392
  if not is_originally_list:
393
  images_pil = [images_pil]
394
 
395
  image_filenames_for_json = []
396
  for img_index, pil_image in enumerate(images_pil):
397
- # Ensure it's actually a PIL Image object before proceeding
398
  if not isinstance(pil_image, Image.Image):
399
  print(f"Warning: Expected PIL Image for key '{key}' in task {task_id_s}, got {type(pil_image)}. Skipping image.")
400
  continue
401
 
402
- # Use object ID to check if this specific image instance is already saved
403
  img_id = id(pil_image)
404
  if img_id in image_paths_in_zip:
405
- # If already saved, just add its filename to the list
406
  image_filenames_for_json.append(image_paths_in_zip[img_id])
407
- continue # Move to the next image in the list
408
 
409
- # Image not saved yet, create filename and save path
410
  img_filename_in_zip = f"task{task_id_s}_{key}_{img_index}.png"
411
  img_save_path = os.path.join(tmpdir, img_filename_in_zip)
412
 
413
  try:
414
- # Save the image to the temporary directory
415
  pil_image.save(img_save_path, "PNG")
416
  image_filenames_for_json.append(img_filename_in_zip)
417
- # Store the mapping from image ID to its filename in the zip
418
  image_paths_in_zip[img_id] = img_filename_in_zip
419
  except Exception as e:
420
  print(f"Error saving image {img_filename_in_zip} for task {task_id_s}: {e}")
421
- # Optionally decide if you want to continue or fail here
422
 
423
- # Update the params_copy with the list of filenames (or single filename)
424
  if image_filenames_for_json:
425
  params_copy[key] = image_filenames_for_json if is_originally_list else image_filenames_for_json[0]
426
  else:
427
- # If no images were successfully processed for this key, remove it
428
  params_copy.pop(key, None)
429
 
430
 
431
- # Clean up parameters before adding to manifest
432
  params_copy.pop('state', None)
433
- params_copy.pop('start_image_data_base64', None) # Don't need base64 in saved queue
434
  params_copy.pop('end_image_data_base64', None)
435
- # Also remove the actual PIL data if it somehow remained
436
  params_copy.pop('start_image_data', None)
437
  params_copy.pop('end_image_data', None)
438
 
439
  manifest_entry = {
440
  "id": task.get('id'),
441
  "params": params_copy,
442
- # Keep other necessary top-level task info if needed, like repeats etc.
443
- # Example: "repeats": task.get('repeats', 1)
444
  }
445
  queue_manifest.append(manifest_entry)
446
 
447
- # --- Create queue.json content ---
448
  manifest_path = os.path.join(tmpdir, "queue.json")
449
  try:
450
  with open(manifest_path, 'w', encoding='utf-8') as f:
451
- # Dump only the relevant manifest data
452
  json.dump(queue_manifest, f, indent=4)
453
  except Exception as e:
454
  print(f"Error writing queue.json: {e}")
455
  gr.Warning("Failed to create queue manifest.")
456
- return None # Return None on failure
457
 
458
- # --- Create the zip file in memory ---
459
  try:
460
  with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
461
- # Add queue.json
462
  zf.write(manifest_path, arcname="queue.json")
463
 
464
- # Add all unique images that were saved to the temp dir
465
  for saved_img_rel_path in image_paths_in_zip.values():
466
  saved_img_abs_path = os.path.join(tmpdir, saved_img_rel_path)
467
  if os.path.exists(saved_img_abs_path):
468
  zf.write(saved_img_abs_path, arcname=saved_img_rel_path)
469
  else:
470
- # This shouldn't happen if saving was successful, but good to check
471
  print(f"Warning: Image file {saved_img_rel_path} not found during zipping.")
472
 
473
- # --- Prepare for return ---
474
- # Move buffer position to the beginning
475
  zip_buffer.seek(0)
476
- # Read the binary content
477
  zip_binary_content = zip_buffer.getvalue()
478
- # Encode as base64 string
479
  zip_base64 = base64.b64encode(zip_binary_content).decode('utf-8')
480
  print(f"Queue successfully prepared as base64 string ({len(zip_base64)} chars).")
481
  return zip_base64
@@ -483,18 +456,17 @@ def save_queue_action(state):
483
  except Exception as e:
484
  print(f"Error creating zip file in memory: {e}")
485
  gr.Warning("Failed to create zip data for download.")
486
- return None # Return None on failure
487
  finally:
488
  zip_buffer.close()
489
 
490
  def load_queue_action(filepath, state):
491
  global task_id
492
  gen = get_gen_info(state)
493
- original_queue = gen.get("queue", []) # Store original queue for error case
494
 
495
  if not filepath or not hasattr(filepath, 'name') or not Path(filepath.name).is_file():
496
  print("[load_queue_action] Warning: No valid file selected or file not found.")
497
- # Return the current state of the DataFrame
498
  return update_queue_data(original_queue)
499
 
500
  newly_loaded_queue = []
@@ -518,7 +490,6 @@ def load_queue_action(filepath, state):
518
  print(f"[load_queue_action] Manifest loaded. Processing {len(loaded_manifest)} tasks.")
519
 
520
  for task_index, task_data in enumerate(loaded_manifest):
521
- # (Keep the existing task processing logic here...)
522
  if task_data is None or not isinstance(task_data, dict):
523
  print(f"[load_queue_action] Skipping invalid task data at index {task_index}")
524
  continue
@@ -528,7 +499,7 @@ def load_queue_action(filepath, state):
528
  max_id_in_file = max(max_id_in_file, task_id_loaded)
529
  loaded_pil_images = {}
530
  image_keys = ["image_start", "image_end", "image_refs"]
531
- params['state'] = state # Add state back temporarily for consistency if needed by internal logic, but it's removed before saving
532
 
533
  for key in image_keys:
534
  image_filenames = params.get(key)
@@ -544,26 +515,22 @@ def load_queue_action(filepath, state):
544
  continue
545
  try:
546
  pil_image = Image.open(img_load_path)
547
- # Ensure the image data is loaded into memory before the temp dir is cleaned up
548
  pil_image.load()
549
- # Convert image right after loading
550
  converted_image = convert_image(pil_image)
551
  loaded_pils.append(converted_image)
552
- pil_image.close() # Close the file handle
553
  except Exception as img_e:
554
  print(f"[load_queue_action] Error loading image {img_filename_in_zip}: {img_e}")
555
  if loaded_pils:
556
  params[key] = loaded_pils if is_list else loaded_pils[0]
557
- loaded_pil_images[key] = params[key] # Store loaded PILs for preview generation
558
  else: params.pop(key, None)
559
 
560
- # Generate preview base64 strings
561
  primary_preview_pil, secondary_preview_pil = None, None
562
  start_prev_pil_list = loaded_pil_images.get("image_start")
563
  end_prev_pil_list = loaded_pil_images.get("image_end")
564
  ref_prev_pil_list = loaded_pil_images.get("image_refs")
565
 
566
- # Extract first image for preview if available
567
  if start_prev_pil_list:
568
  primary_preview_pil = start_prev_pil_list[0] if isinstance(start_prev_pil_list, list) and start_prev_pil_list else start_prev_pil_list if not isinstance(start_prev_pil_list, list) else None
569
  if end_prev_pil_list:
@@ -571,97 +538,102 @@ def load_queue_action(filepath, state):
571
  elif ref_prev_pil_list and isinstance(ref_prev_pil_list, list) and ref_prev_pil_list:
572
  primary_preview_pil = ref_prev_pil_list[0]
573
 
574
- # Generate base64 only if PIL image exists
575
  start_b64 = [pil_to_base64_uri(primary_preview_pil, format="jpeg", quality=70)] if primary_preview_pil else None
576
  end_b64 = [pil_to_base64_uri(secondary_preview_pil, format="jpeg", quality=70)] if secondary_preview_pil else None
577
 
578
- # Get top-level image data (PIL objects) for runtime task
579
  top_level_start_image = loaded_pil_images.get("image_start")
580
  top_level_end_image = loaded_pil_images.get("image_end")
581
 
582
- # Construct the runtime task dictionary
583
  runtime_task = {
584
  "id": task_id_loaded,
585
- "params": params.copy(), # Use a copy of params
586
- # Extract necessary params for top level if they exist
587
  "repeats": params.get('repeat_generation', 1),
588
  "length": params.get('video_length'),
589
  "steps": params.get('num_inference_steps'),
590
  "prompt": params.get('prompt'),
591
- # Store the actual loaded PIL image data here
592
  "start_image_data": top_level_start_image,
593
  "end_image_data": top_level_end_image,
594
- # Store base64 previews generated above
595
  "start_image_data_base64": start_b64,
596
  "end_image_data_base64": end_b64,
597
  }
598
  newly_loaded_queue.append(runtime_task)
599
  print(f"[load_queue_action] Processed task {task_index+1}/{len(loaded_manifest)}, ID: {task_id_loaded}")
600
 
601
- # --- State Update ---
602
  with lock:
603
  print("[load_queue_action] Acquiring lock to update state...")
604
- gen["queue"] = newly_loaded_queue[:] # Replace the queue in the state
605
- local_queue_copy_for_global_ref = gen["queue"][:] # Copy for global ref update
606
- current_max_id_in_new_queue = max([t['id'] for t in newly_loaded_queue if 'id' in t] + [0]) # Safer max ID calculation
607
 
608
- # Update global task ID only if the loaded max ID is higher
609
  if current_max_id_in_new_queue > task_id:
610
  print(f"[load_queue_action] Updating global task_id from {task_id} to {current_max_id_in_new_queue + 1}")
611
- task_id = current_max_id_in_new_queue + 1 # Ensure next ID is unique
612
  else:
613
  print(f"[load_queue_action] Global task_id ({task_id}) is >= max in file ({current_max_id_in_new_queue}). Not changing task_id.")
614
 
615
  gen["prompts_max"] = len(newly_loaded_queue)
616
  print("[load_queue_action] State update complete. Releasing lock.")
617
 
618
- # --- Global Reference Update ---
619
  if local_queue_copy_for_global_ref is not None:
620
  print("[load_queue_action] Updating global queue reference...")
621
  update_global_queue_ref(local_queue_copy_for_global_ref)
622
  else:
623
- # This case should ideally not be reached if state update happens
624
  print("[load_queue_action] Warning: Skipping global ref update as local copy is None.")
625
 
626
  print(f"[load_queue_action] Queue load successful. Returning DataFrame update for {len(newly_loaded_queue)} tasks.")
627
- # *** Return the DataFrame update object ***
628
  return update_queue_data(newly_loaded_queue)
629
 
630
  except (ValueError, zipfile.BadZipFile, FileNotFoundError, Exception) as e:
631
  error_message = f"Error during queue load: {e}"
632
  print(f"[load_queue_action] Caught error: {error_message}")
633
  traceback.print_exc()
634
- # Optionally show a Gradio warning/error to the user
635
- gr.Warning(f"Failed to load queue: {error_message[:200]}") # Show truncated error
636
 
637
- # *** Return the DataFrame update for the original queue ***
638
  print("[load_queue_action] Load failed. Returning DataFrame update for original queue.")
639
  return update_queue_data(original_queue)
640
  finally:
641
- # Clean up the uploaded file object if it exists and has a path
642
  if filepath and hasattr(filepath, 'name') and filepath.name and os.path.exists(filepath.name):
643
  try:
644
- # Gradio often uses temp files, attempting removal is good practice
645
- # os.remove(filepath.name)
646
- # print(f"[load_queue_action] Cleaned up temporary upload file: {filepath.name}")
647
- pass # Let Gradio manage its temp files unless specifically needed
648
  except OSError as e:
649
- # Ignore errors like "file not found" if already cleaned up
650
  print(f"[load_queue_action] Info: Could not remove temp file {filepath.name}: {e}")
651
  pass
652
 
653
  def clear_queue_action(state):
654
  gen = get_gen_info(state)
655
  queue = gen.get("queue", [])
656
- if not queue:
657
- gr.Info("Queue is already empty.")
658
- return update_queue_data([])
659
 
660
  with lock:
661
- queue.clear()
662
- gen["prompts_max"] = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
663
 
664
- gr.Info("Queue cleared.")
665
  return update_queue_data([])
666
 
667
  def autosave_queue():
@@ -725,7 +697,7 @@ def autosave_queue():
725
  if os.path.exists(saved_img_abs_path):
726
  zf.write(saved_img_abs_path, arcname=saved_img_rel_path)
727
  return output_filename
728
- return None # Should not happen if queue has items
729
 
730
  saved_path = _save_queue_to_file(global_queue_ref, AUTOSAVE_FILENAME)
731
 
@@ -740,17 +712,15 @@ def autosave_queue():
740
 
741
  def autoload_queue(state):
742
  global task_id
743
- # Initial check using the original state
744
  try:
745
- gen = get_gen_info(state) # Make sure initial state is a dict
746
  original_queue = gen.get("queue", [])
747
  except AttributeError:
748
  print("[autoload_queue] Error: Initial state is not a dictionary. Cannot autoload.")
749
- # Return default values indicating no load occurred and the state is unchanged
750
- return gr.update(visible=False), False, state # Return an empty DF update
751
 
752
  loaded_flag = False
753
- dataframe_update = update_queue_data(original_queue) # Default update is the original queue
754
 
755
  if not original_queue and Path(AUTOSAVE_FILENAME).is_file():
756
  print(f"Autoloading queue from {AUTOSAVE_FILENAME}...")
@@ -758,38 +728,32 @@ def autoload_queue(state):
758
  def __init__(self, name):
759
  self.name = name
760
  mock_filepath = MockFile(AUTOSAVE_FILENAME)
761
-
762
- # Call load_queue_action, it modifies 'state' internally and returns a DataFrame update
763
  dataframe_update = load_queue_action(mock_filepath, state)
764
 
765
- # Now check the 'state' dictionary which should have been modified by load_queue_action
766
- gen = get_gen_info(state) # Use the (potentially) modified state dictionary
767
  loaded_queue_after_action = gen.get("queue", [])
768
 
769
- if loaded_queue_after_action: # Check if the queue in the state is now populated
770
  print(f"Autoload successful. Loaded {len(loaded_queue_after_action)} tasks into state.")
771
  loaded_flag = True
772
- # Global ref update was already done inside load_queue_action if successful
773
  else:
774
  print("Autoload attempted but queue in state remains empty (file might be empty or invalid).")
775
- # Ensure state reflects empty queue if load failed but file existed
776
  with lock:
777
  gen["queue"] = []
778
  gen["prompts_max"] = 0
779
  update_global_queue_ref([])
780
- dataframe_update = update_queue_data([]) # Ensure UI shows empty queue
781
 
782
- else: # Handle cases where autoload shouldn't happen
783
  if original_queue:
784
  print("Autoload skipped: Queue is not empty.")
785
- update_global_queue_ref(original_queue) # Ensure global ref matches current state
786
- dataframe_update = update_queue_data(original_queue) # UI should show current queue
787
  else:
788
  print(f"Autoload skipped: {AUTOSAVE_FILENAME} not found.")
789
- update_global_queue_ref([]) # Ensure global ref is empty
790
- dataframe_update = update_queue_data([]) # UI should show empty queue
791
 
792
- # Return the DataFrame update needed for the UI, the flag, and the final state dictionary
793
  return dataframe_update, loaded_flag, state
794
 
795
 
 
362
  gen = get_gen_info(state)
363
  queue = gen.get("queue", [])
364
 
365
+ if not queue or len(queue) <=1 :
366
  gr.Info("Queue is empty. Nothing to save.")
367
+ return None
368
 
 
369
  zip_buffer = io.BytesIO()
370
 
 
371
  with tempfile.TemporaryDirectory() as tmpdir:
372
  queue_manifest = []
373
+ image_paths_in_zip = {}
374
 
375
  for task_index, task in enumerate(queue):
 
376
  if task is None or not isinstance(task, dict) or task_index == 0: continue
377
 
378
  params_copy = task.get('params', {}).copy()
379
+ task_id_s = task.get('id', f"task_{task_index}")
380
 
381
  image_keys = ["image_start", "image_end", "image_refs"]
382
  for key in image_keys:
 
384
  if images_pil is None:
385
  continue
386
 
 
387
  is_originally_list = isinstance(images_pil, list)
388
  if not is_originally_list:
389
  images_pil = [images_pil]
390
 
391
  image_filenames_for_json = []
392
  for img_index, pil_image in enumerate(images_pil):
 
393
  if not isinstance(pil_image, Image.Image):
394
  print(f"Warning: Expected PIL Image for key '{key}' in task {task_id_s}, got {type(pil_image)}. Skipping image.")
395
  continue
396
 
 
397
  img_id = id(pil_image)
398
  if img_id in image_paths_in_zip:
 
399
  image_filenames_for_json.append(image_paths_in_zip[img_id])
400
+ continue
401
 
 
402
  img_filename_in_zip = f"task{task_id_s}_{key}_{img_index}.png"
403
  img_save_path = os.path.join(tmpdir, img_filename_in_zip)
404
 
405
  try:
 
406
  pil_image.save(img_save_path, "PNG")
407
  image_filenames_for_json.append(img_filename_in_zip)
 
408
  image_paths_in_zip[img_id] = img_filename_in_zip
409
  except Exception as e:
410
  print(f"Error saving image {img_filename_in_zip} for task {task_id_s}: {e}")
 
411
 
 
412
  if image_filenames_for_json:
413
  params_copy[key] = image_filenames_for_json if is_originally_list else image_filenames_for_json[0]
414
  else:
 
415
  params_copy.pop(key, None)
416
 
417
 
 
418
  params_copy.pop('state', None)
419
+ params_copy.pop('start_image_data_base64', None)
420
  params_copy.pop('end_image_data_base64', None)
 
421
  params_copy.pop('start_image_data', None)
422
  params_copy.pop('end_image_data', None)
423
 
424
  manifest_entry = {
425
  "id": task.get('id'),
426
  "params": params_copy,
 
 
427
  }
428
  queue_manifest.append(manifest_entry)
429
 
 
430
  manifest_path = os.path.join(tmpdir, "queue.json")
431
  try:
432
  with open(manifest_path, 'w', encoding='utf-8') as f:
 
433
  json.dump(queue_manifest, f, indent=4)
434
  except Exception as e:
435
  print(f"Error writing queue.json: {e}")
436
  gr.Warning("Failed to create queue manifest.")
437
+ return None
438
 
 
439
  try:
440
  with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
 
441
  zf.write(manifest_path, arcname="queue.json")
442
 
 
443
  for saved_img_rel_path in image_paths_in_zip.values():
444
  saved_img_abs_path = os.path.join(tmpdir, saved_img_rel_path)
445
  if os.path.exists(saved_img_abs_path):
446
  zf.write(saved_img_abs_path, arcname=saved_img_rel_path)
447
  else:
 
448
  print(f"Warning: Image file {saved_img_rel_path} not found during zipping.")
449
 
 
 
450
  zip_buffer.seek(0)
 
451
  zip_binary_content = zip_buffer.getvalue()
 
452
  zip_base64 = base64.b64encode(zip_binary_content).decode('utf-8')
453
  print(f"Queue successfully prepared as base64 string ({len(zip_base64)} chars).")
454
  return zip_base64
 
456
  except Exception as e:
457
  print(f"Error creating zip file in memory: {e}")
458
  gr.Warning("Failed to create zip data for download.")
459
+ return None
460
  finally:
461
  zip_buffer.close()
462
 
463
  def load_queue_action(filepath, state):
464
  global task_id
465
  gen = get_gen_info(state)
466
+ original_queue = gen.get("queue", [])
467
 
468
  if not filepath or not hasattr(filepath, 'name') or not Path(filepath.name).is_file():
469
  print("[load_queue_action] Warning: No valid file selected or file not found.")
 
470
  return update_queue_data(original_queue)
471
 
472
  newly_loaded_queue = []
 
490
  print(f"[load_queue_action] Manifest loaded. Processing {len(loaded_manifest)} tasks.")
491
 
492
  for task_index, task_data in enumerate(loaded_manifest):
 
493
  if task_data is None or not isinstance(task_data, dict):
494
  print(f"[load_queue_action] Skipping invalid task data at index {task_index}")
495
  continue
 
499
  max_id_in_file = max(max_id_in_file, task_id_loaded)
500
  loaded_pil_images = {}
501
  image_keys = ["image_start", "image_end", "image_refs"]
502
+ params['state'] = state
503
 
504
  for key in image_keys:
505
  image_filenames = params.get(key)
 
515
  continue
516
  try:
517
  pil_image = Image.open(img_load_path)
 
518
  pil_image.load()
 
519
  converted_image = convert_image(pil_image)
520
  loaded_pils.append(converted_image)
521
+ pil_image.close()
522
  except Exception as img_e:
523
  print(f"[load_queue_action] Error loading image {img_filename_in_zip}: {img_e}")
524
  if loaded_pils:
525
  params[key] = loaded_pils if is_list else loaded_pils[0]
526
+ loaded_pil_images[key] = params[key]
527
  else: params.pop(key, None)
528
 
 
529
  primary_preview_pil, secondary_preview_pil = None, None
530
  start_prev_pil_list = loaded_pil_images.get("image_start")
531
  end_prev_pil_list = loaded_pil_images.get("image_end")
532
  ref_prev_pil_list = loaded_pil_images.get("image_refs")
533
 
 
534
  if start_prev_pil_list:
535
  primary_preview_pil = start_prev_pil_list[0] if isinstance(start_prev_pil_list, list) and start_prev_pil_list else start_prev_pil_list if not isinstance(start_prev_pil_list, list) else None
536
  if end_prev_pil_list:
 
538
  elif ref_prev_pil_list and isinstance(ref_prev_pil_list, list) and ref_prev_pil_list:
539
  primary_preview_pil = ref_prev_pil_list[0]
540
 
 
541
  start_b64 = [pil_to_base64_uri(primary_preview_pil, format="jpeg", quality=70)] if primary_preview_pil else None
542
  end_b64 = [pil_to_base64_uri(secondary_preview_pil, format="jpeg", quality=70)] if secondary_preview_pil else None
543
 
 
544
  top_level_start_image = loaded_pil_images.get("image_start")
545
  top_level_end_image = loaded_pil_images.get("image_end")
546
 
 
547
  runtime_task = {
548
  "id": task_id_loaded,
549
+ "params": params.copy(),
 
550
  "repeats": params.get('repeat_generation', 1),
551
  "length": params.get('video_length'),
552
  "steps": params.get('num_inference_steps'),
553
  "prompt": params.get('prompt'),
 
554
  "start_image_data": top_level_start_image,
555
  "end_image_data": top_level_end_image,
 
556
  "start_image_data_base64": start_b64,
557
  "end_image_data_base64": end_b64,
558
  }
559
  newly_loaded_queue.append(runtime_task)
560
  print(f"[load_queue_action] Processed task {task_index+1}/{len(loaded_manifest)}, ID: {task_id_loaded}")
561
 
 
562
  with lock:
563
  print("[load_queue_action] Acquiring lock to update state...")
564
+ gen["queue"] = newly_loaded_queue[:]
565
+ local_queue_copy_for_global_ref = gen["queue"][:]
566
+ current_max_id_in_new_queue = max([t['id'] for t in newly_loaded_queue if 'id' in t] + [0])
567
 
 
568
  if current_max_id_in_new_queue > task_id:
569
  print(f"[load_queue_action] Updating global task_id from {task_id} to {current_max_id_in_new_queue + 1}")
570
+ task_id = current_max_id_in_new_queue + 1
571
  else:
572
  print(f"[load_queue_action] Global task_id ({task_id}) is >= max in file ({current_max_id_in_new_queue}). Not changing task_id.")
573
 
574
  gen["prompts_max"] = len(newly_loaded_queue)
575
  print("[load_queue_action] State update complete. Releasing lock.")
576
 
 
577
  if local_queue_copy_for_global_ref is not None:
578
  print("[load_queue_action] Updating global queue reference...")
579
  update_global_queue_ref(local_queue_copy_for_global_ref)
580
  else:
 
581
  print("[load_queue_action] Warning: Skipping global ref update as local copy is None.")
582
 
583
  print(f"[load_queue_action] Queue load successful. Returning DataFrame update for {len(newly_loaded_queue)} tasks.")
 
584
  return update_queue_data(newly_loaded_queue)
585
 
586
  except (ValueError, zipfile.BadZipFile, FileNotFoundError, Exception) as e:
587
  error_message = f"Error during queue load: {e}"
588
  print(f"[load_queue_action] Caught error: {error_message}")
589
  traceback.print_exc()
590
+ gr.Warning(f"Failed to load queue: {error_message[:200]}")
 
591
 
 
592
  print("[load_queue_action] Load failed. Returning DataFrame update for original queue.")
593
  return update_queue_data(original_queue)
594
  finally:
 
595
  if filepath and hasattr(filepath, 'name') and filepath.name and os.path.exists(filepath.name):
596
  try:
597
+ pass
 
 
 
598
  except OSError as e:
 
599
  print(f"[load_queue_action] Info: Could not remove temp file {filepath.name}: {e}")
600
  pass
601
 
602
  def clear_queue_action(state):
603
  gen = get_gen_info(state)
604
  queue = gen.get("queue", [])
605
+ aborted_current = False
606
+ cleared_pending = False
 
607
 
608
  with lock:
609
+ if "in_progress" in gen and gen["in_progress"]:
610
+ print("Clear Queue: Signalling abort for in-progress task.")
611
+ gen["abort"] = True
612
+ gen["extra_orders"] = 0
613
+ if wan_model is not None:
614
+ wan_model._interrupt = True
615
+ aborted_current = True
616
+
617
+ if queue:
618
+ if len(queue) > 1 or (len(queue) == 1 and queue[0] is not None and queue[0].get('id') is not None):
619
+ print(f"Clear Queue: Clearing {len(queue)} tasks from queue.")
620
+ queue.clear()
621
+ cleared_pending = True
622
+ else:
623
+ pass
624
+
625
+ if aborted_current or cleared_pending:
626
+ gen["prompts_max"] = 0
627
+
628
+ if aborted_current and cleared_pending:
629
+ gr.Info("Queue cleared and current generation aborted.")
630
+ elif aborted_current:
631
+ gr.Info("Current generation aborted.")
632
+ elif cleared_pending:
633
+ gr.Info("Queue cleared.")
634
+ else:
635
+ gr.Info("Queue is already empty or only contains the active task (which wasn't aborted now).")
636
 
 
637
  return update_queue_data([])
638
 
639
  def autosave_queue():
 
697
  if os.path.exists(saved_img_abs_path):
698
  zf.write(saved_img_abs_path, arcname=saved_img_rel_path)
699
  return output_filename
700
+ return None
701
 
702
  saved_path = _save_queue_to_file(global_queue_ref, AUTOSAVE_FILENAME)
703
 
 
712
 
713
  def autoload_queue(state):
714
  global task_id
 
715
  try:
716
+ gen = get_gen_info(state)
717
  original_queue = gen.get("queue", [])
718
  except AttributeError:
719
  print("[autoload_queue] Error: Initial state is not a dictionary. Cannot autoload.")
720
+ return gr.update(visible=False), False, state
 
721
 
722
  loaded_flag = False
723
+ dataframe_update = update_queue_data(original_queue)
724
 
725
  if not original_queue and Path(AUTOSAVE_FILENAME).is_file():
726
  print(f"Autoloading queue from {AUTOSAVE_FILENAME}...")
 
728
  def __init__(self, name):
729
  self.name = name
730
  mock_filepath = MockFile(AUTOSAVE_FILENAME)
 
 
731
  dataframe_update = load_queue_action(mock_filepath, state)
732
 
733
+ gen = get_gen_info(state)
 
734
  loaded_queue_after_action = gen.get("queue", [])
735
 
736
+ if loaded_queue_after_action:
737
  print(f"Autoload successful. Loaded {len(loaded_queue_after_action)} tasks into state.")
738
  loaded_flag = True
 
739
  else:
740
  print("Autoload attempted but queue in state remains empty (file might be empty or invalid).")
 
741
  with lock:
742
  gen["queue"] = []
743
  gen["prompts_max"] = 0
744
  update_global_queue_ref([])
745
+ dataframe_update = update_queue_data([])
746
 
747
+ else:
748
  if original_queue:
749
  print("Autoload skipped: Queue is not empty.")
750
+ update_global_queue_ref(original_queue)
751
+ dataframe_update = update_queue_data(original_queue)
752
  else:
753
  print(f"Autoload skipped: {AUTOSAVE_FILENAME} not found.")
754
+ update_global_queue_ref([])
755
+ dataframe_update = update_queue_data([])
756
 
 
757
  return dataframe_update, loaded_flag, state
758
 
759