mirror of
https://git.datalinker.icu/ltdrdata/ComfyUI-Manager
synced 2025-12-09 06:04:31 +08:00
feat: support task batch
POST /v2/manager/queue/batch
GET /v2/manager/queue/history_list
GET /v2/manager/queue/history?id={id}
GET /v2/manager/queue/abort_current
This commit is contained in:
parent
34efbe9262
commit
5ea7bf3683
@ -202,6 +202,7 @@ manager_snapshot_path = None
|
||||
manager_pip_overrides_path = None
|
||||
manager_pip_blacklist_path = None
|
||||
manager_components_path = None
|
||||
manager_batch_history_path = None
|
||||
|
||||
def update_user_directory(user_dir):
|
||||
global manager_files_path
|
||||
@ -212,6 +213,7 @@ def update_user_directory(user_dir):
|
||||
global manager_pip_overrides_path
|
||||
global manager_pip_blacklist_path
|
||||
global manager_components_path
|
||||
global manager_batch_history_path
|
||||
|
||||
manager_files_path = os.path.abspath(os.path.join(user_dir, 'default', 'ComfyUI-Manager'))
|
||||
if not os.path.exists(manager_files_path):
|
||||
@ -231,9 +233,13 @@ def update_user_directory(user_dir):
|
||||
manager_pip_blacklist_path = os.path.join(manager_files_path, "pip_blacklist.list")
|
||||
manager_components_path = os.path.join(manager_files_path, "components")
|
||||
manager_util.cache_dir = os.path.join(manager_files_path, "cache")
|
||||
manager_batch_history_path = os.path.join(manager_files_path, "batch_history")
|
||||
|
||||
if not os.path.exists(manager_util.cache_dir):
|
||||
os.makedirs(manager_util.cache_dir)
|
||||
|
||||
if not os.path.exists(manager_batch_history_path):
|
||||
os.makedirs(manager_batch_history_path)
|
||||
|
||||
try:
|
||||
import folder_paths
|
||||
|
||||
@ -16,7 +16,7 @@ from datetime import datetime
|
||||
from server import PromptServer
|
||||
import logging
|
||||
import asyncio
|
||||
import queue
|
||||
from collections import deque
|
||||
|
||||
from . import manager_core as core
|
||||
from . import manager_util
|
||||
@ -389,16 +389,73 @@ def nickname_filter(json_obj):
|
||||
return json_obj
|
||||
|
||||
|
||||
task_queue = queue.Queue()
|
||||
nodepack_result = {}
|
||||
model_result = {}
|
||||
class TaskBatch:
|
||||
def __init__(self, batch_json, tasks, failed):
|
||||
self.nodepack_result = {}
|
||||
self.model_result = {}
|
||||
self.batch_id = batch_json.get('batch_id') if batch_json is not None else None
|
||||
self.batch_json = batch_json
|
||||
self.tasks = tasks
|
||||
self.current_index = 0
|
||||
self.stats = {}
|
||||
self.failed = failed if failed is not None else set()
|
||||
self.is_aborted = False
|
||||
|
||||
def is_done(self):
|
||||
return len(self.tasks) <= self.current_index
|
||||
|
||||
def get_next(self):
|
||||
if self.is_done():
|
||||
return None
|
||||
|
||||
item = self.tasks[self.current_index]
|
||||
self.current_index += 1
|
||||
return item
|
||||
|
||||
def done_count(self):
|
||||
return len(self.nodepack_result) + len(self.model_result)
|
||||
|
||||
def total_count(self):
|
||||
return len(self.tasks)
|
||||
|
||||
def abort(self):
|
||||
self.is_aborted = True
|
||||
|
||||
def finalize(self):
|
||||
if self.batch_id is not None:
|
||||
batch_path = os.path.join(core.manager_batch_history_path, self.batch_id+".json")
|
||||
json_obj = {
|
||||
"batch": self.batch_json,
|
||||
"nodepack_result": self.nodepack_result,
|
||||
"model_result": self.model_result,
|
||||
"failed": list(self.failed)
|
||||
}
|
||||
with open(batch_path, "w") as json_file:
|
||||
json.dump(json_obj, json_file, indent=4)
|
||||
|
||||
|
||||
temp_queue_batch = []
|
||||
task_batch_queue = deque()
|
||||
tasks_in_progress = set()
|
||||
task_worker_lock = threading.Lock()
|
||||
aborted_batch = None
|
||||
|
||||
|
||||
def finalize_temp_queue_batch(batch_json=None, failed=None):
|
||||
"""
|
||||
make temp_queue_batch as a batch snapshot and add to batch_queue
|
||||
"""
|
||||
|
||||
global temp_queue_batch
|
||||
|
||||
if len(temp_queue_batch):
|
||||
batch = TaskBatch(batch_json, temp_queue_batch, failed)
|
||||
task_batch_queue.append(batch)
|
||||
temp_queue_batch = []
|
||||
|
||||
|
||||
async def task_worker():
|
||||
global task_queue
|
||||
global nodepack_result
|
||||
global model_result
|
||||
global tasks_in_progress
|
||||
|
||||
async def do_install(item) -> str:
|
||||
@ -411,8 +468,7 @@ async def task_worker():
|
||||
return f"Cannot resolve install target: '{node_spec_str}'"
|
||||
|
||||
node_name, version_spec, is_specified = node_spec
|
||||
res = await core.unified_manager.install_by_id(node_name, version_spec, channel, mode, return_postinstall=skip_post_install)
|
||||
# discard post install if skip_post_install mode
|
||||
res = await core.unified_manager.install_by_id(node_name, version_spec, channel, mode, return_postinstall=skip_post_install) # discard post install if skip_post_install mode
|
||||
|
||||
if res.action not in ['skip', 'enable', 'install-git', 'install-cnr', 'switch-cnr']:
|
||||
logging.error(f"[ComfyUI-Manager] Installation failed:\n{res.msg}")
|
||||
@ -427,6 +483,11 @@ async def task_worker():
|
||||
traceback.print_exc()
|
||||
return f"Installation failed:\n{node_spec_str}"
|
||||
|
||||
async def do_enable(item) -> str:
|
||||
ui_id, cnr_id = item
|
||||
core.unified_manager.unified_enable(cnr_id)
|
||||
return 'success'
|
||||
|
||||
async def do_update(item):
|
||||
ui_id, node_name, node_ver = item
|
||||
|
||||
@ -588,31 +649,45 @@ async def task_worker():
|
||||
|
||||
return f"Model installation error: {model_url}"
|
||||
|
||||
stats = {}
|
||||
|
||||
while True:
|
||||
done_count = len(nodepack_result) + len(model_result)
|
||||
total_count = done_count + task_queue.qsize()
|
||||
with task_worker_lock:
|
||||
if len(task_batch_queue) > 0:
|
||||
cur_batch = task_batch_queue[0]
|
||||
else:
|
||||
logging.info(f"\n[ComfyUI-Manager] All tasks are completed.")
|
||||
logging.info("\nAfter restarting ComfyUI, please refresh the browser.")
|
||||
|
||||
if task_queue.empty():
|
||||
logging.info(f"\n[ComfyUI-Manager] Queued works are completed.\n{stats}")
|
||||
res = {'status': 'all-done'}
|
||||
|
||||
logging.info("\nAfter restarting ComfyUI, please refresh the browser.")
|
||||
PromptServer.instance.send_sync("cm-queue-status",
|
||||
{'status': 'done',
|
||||
'nodepack_result': nodepack_result, 'model_result': model_result,
|
||||
'total_count': total_count, 'done_count': done_count})
|
||||
nodepack_result = {}
|
||||
task_queue = queue.Queue()
|
||||
return # terminate worker thread
|
||||
PromptServer.instance.send_sync("cm-queue-status", res)
|
||||
|
||||
return
|
||||
|
||||
if cur_batch.is_done():
|
||||
logging.info(f"\n[ComfyUI-Manager] A tasks batch(batch_id={cur_batch.batch_id}) is completed.\nstat={cur_batch.stats}")
|
||||
|
||||
res = {'status': 'batch-done',
|
||||
'nodepack_result': cur_batch.nodepack_result,
|
||||
'model_result': cur_batch.model_result,
|
||||
'total_count': cur_batch.total_count(),
|
||||
'done_count': cur_batch.done_count(),
|
||||
'batch_id': cur_batch.batch_id,
|
||||
'remaining_batch_count': len(task_batch_queue) }
|
||||
|
||||
PromptServer.instance.send_sync("cm-queue-status", res)
|
||||
cur_batch.finalize()
|
||||
task_batch_queue.popleft()
|
||||
continue
|
||||
|
||||
with task_worker_lock:
|
||||
kind, item = task_queue.get()
|
||||
kind, item = cur_batch.get_next()
|
||||
tasks_in_progress.add((kind, item[0]))
|
||||
|
||||
try:
|
||||
if kind == 'install':
|
||||
msg = await do_install(item)
|
||||
elif kind == 'enable':
|
||||
msg = await do_enable(item)
|
||||
elif kind == 'install-model':
|
||||
msg = await do_install_model(item)
|
||||
elif kind == 'update':
|
||||
@ -636,28 +711,128 @@ async def task_worker():
|
||||
with task_worker_lock:
|
||||
tasks_in_progress.remove((kind, item[0]))
|
||||
|
||||
ui_id = item[0]
|
||||
if kind == 'install-model':
|
||||
model_result[ui_id] = msg
|
||||
ui_target = "model_manager"
|
||||
elif kind == 'update-main':
|
||||
nodepack_result[ui_id] = msg
|
||||
ui_target = "main"
|
||||
elif kind == 'update-comfyui':
|
||||
nodepack_result['comfyui'] = msg
|
||||
ui_target = "main"
|
||||
elif kind == 'update':
|
||||
nodepack_result[ui_id] = msg['msg']
|
||||
ui_target = "nodepack_manager"
|
||||
else:
|
||||
nodepack_result[ui_id] = msg
|
||||
ui_target = "nodepack_manager"
|
||||
ui_id = item[0]
|
||||
if kind == 'install-model':
|
||||
cur_batch.model_result[ui_id] = msg
|
||||
ui_target = "model_manager"
|
||||
elif kind == 'update-main':
|
||||
cur_batch.nodepack_result[ui_id] = msg
|
||||
ui_target = "main"
|
||||
elif kind == 'update-comfyui':
|
||||
cur_batch.nodepack_result['comfyui'] = msg
|
||||
ui_target = "main"
|
||||
elif kind == 'update':
|
||||
cur_batch.nodepack_result[ui_id] = msg['msg']
|
||||
ui_target = "nodepack_manager"
|
||||
else:
|
||||
cur_batch.nodepack_result[ui_id] = msg
|
||||
ui_target = "nodepack_manager"
|
||||
|
||||
stats[kind] = stats.get(kind, 0) + 1
|
||||
cur_batch.stats[kind] = cur_batch.stats.get(kind, 0) + 1
|
||||
|
||||
PromptServer.instance.send_sync("cm-queue-status",
|
||||
{'status': 'in_progress', 'target': item[0], 'ui_target': ui_target,
|
||||
'total_count': total_count, 'done_count': done_count})
|
||||
{'status': 'in_progress',
|
||||
'target': item[0],
|
||||
'batch_id': cur_batch.batch_id,
|
||||
'ui_target': ui_target,
|
||||
'total_count': cur_batch.total_count(),
|
||||
'done_count': cur_batch.done_count()})
|
||||
|
||||
|
||||
@routes.post("/v2/manager/queue/batch")
|
||||
async def queue_batch(request):
|
||||
json_data = await request.json()
|
||||
|
||||
failed = set()
|
||||
|
||||
for k, v in json_data.items():
|
||||
if k == 'update_all':
|
||||
await _update_all({'mode': v})
|
||||
|
||||
elif k == 'reinstall':
|
||||
for x in v:
|
||||
res = await _uninstall_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
else:
|
||||
res = await _install_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
elif k == 'install':
|
||||
for x in v:
|
||||
res = await _install_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
elif k == 'uninstall':
|
||||
for x in v:
|
||||
res = await _uninstall_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
elif k == 'update':
|
||||
for x in v:
|
||||
res = await _update_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
elif k == 'update_comfyui':
|
||||
await update_comfyui(None)
|
||||
|
||||
elif k == 'disable':
|
||||
for x in v:
|
||||
await _disable_node(x)
|
||||
|
||||
elif k == 'install_model':
|
||||
for x in v:
|
||||
res = await _install_model(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
elif k == 'fix':
|
||||
for x in v:
|
||||
res = await _fix_custom_node(x)
|
||||
if res.status != 200:
|
||||
failed.add(x[0])
|
||||
|
||||
with task_worker_lock:
|
||||
finalize_temp_queue_batch(json_data, failed)
|
||||
_queue_start()
|
||||
|
||||
return web.json_response({"failed": list(failed)}, content_type='application/json')
|
||||
|
||||
|
||||
@routes.get("/v2/manager/queue/history_list")
|
||||
async def get_history_list(request):
|
||||
history_path = core.manager_batch_history_path
|
||||
|
||||
try:
|
||||
files = [os.path.join(history_path, f) for f in os.listdir(history_path) if os.path.isfile(os.path.join(history_path, f))]
|
||||
files.sort(key=lambda x: os.path.getmtime(x), reverse=True)
|
||||
history_ids = [os.path.basename(f)[:-5] for f in files]
|
||||
|
||||
return web.json_response({"ids": list(history_ids)}, content_type='application/json')
|
||||
except Exception as e:
|
||||
logging.error(f"[ComfyUI-Manager] /v2/manager/queue/history_list - {e}")
|
||||
return web.Response(status=400)
|
||||
|
||||
|
||||
@routes.get("/v2/manager/queue/history")
|
||||
async def get_history(request):
|
||||
try:
|
||||
json_name = request.rel_url.query["id"]+'.json'
|
||||
batch_path = os.path.join(core.manager_batch_history_path, json_name)
|
||||
|
||||
with open(batch_path, 'r', encoding='utf-8') as file:
|
||||
json_str = file.read()
|
||||
json_obj = json.loads(json_str)
|
||||
return web.json_response(json_obj, content_type='application/json')
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"[ComfyUI-Manager] /v2/manager/queue/history - {e}")
|
||||
|
||||
return web.Response(status=400)
|
||||
|
||||
|
||||
@routes.get("/v2/customnode/getmappings")
|
||||
@ -725,6 +900,11 @@ async def fetch_updates(request):
|
||||
|
||||
@routes.get("/v2/manager/queue/update_all")
|
||||
async def update_all(request):
|
||||
json_data = dict(request.rel_url.query)
|
||||
return await _update_all(json_data)
|
||||
|
||||
|
||||
async def _update_all(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403)
|
||||
@ -736,13 +916,13 @@ async def update_all(request):
|
||||
|
||||
await core.save_snapshot_with_postfix('autosave')
|
||||
|
||||
if request.rel_url.query["mode"] == "local":
|
||||
if json_data["mode"] == "local":
|
||||
channel = 'local'
|
||||
else:
|
||||
channel = core.get_config()['channel_url']
|
||||
|
||||
await core.unified_manager.reload(request.rel_url.query["mode"])
|
||||
await core.unified_manager.get_custom_nodes(channel, request.rel_url.query["mode"])
|
||||
await core.unified_manager.reload(json_data["mode"])
|
||||
await core.unified_manager.get_custom_nodes(channel, json_data["mode"])
|
||||
|
||||
for k, v in core.unified_manager.active_nodes.items():
|
||||
if k == 'comfyui-manager':
|
||||
@ -751,7 +931,7 @@ async def update_all(request):
|
||||
continue
|
||||
|
||||
update_item = k, k, v[0]
|
||||
task_queue.put(("update-main", update_item))
|
||||
temp_queue_batch.append(("update-main", update_item))
|
||||
|
||||
for k, v in core.unified_manager.unknown_active_nodes.items():
|
||||
if k == 'comfyui-manager':
|
||||
@ -760,7 +940,7 @@ async def update_all(request):
|
||||
continue
|
||||
|
||||
update_item = k, k, 'unknown'
|
||||
task_queue.put(("update-main", update_item))
|
||||
temp_queue_batch.append(("update-main", update_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
@ -1097,8 +1277,27 @@ async def reinstall_custom_node(request):
|
||||
|
||||
@routes.get("/v2/manager/queue/reset")
|
||||
async def reset_queue(request):
|
||||
global task_queue
|
||||
task_queue = queue.Queue()
|
||||
global task_batch_queue
|
||||
global temp_queue_batch
|
||||
|
||||
with task_worker_lock:
|
||||
temp_queue_batch = []
|
||||
task_batch_queue = deque()
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@routes.get("/v2/manager/queue/abort_current")
|
||||
async def reset_queue(request):
|
||||
global task_batch_queue
|
||||
global temp_queue_batch
|
||||
|
||||
with task_worker_lock:
|
||||
temp_queue_batch = []
|
||||
if len(task_batch_queue) > 0:
|
||||
task_batch_queue[0].abort()
|
||||
task_batch_queue.popleft()
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@ -1107,24 +1306,37 @@ async def queue_count(request):
|
||||
global task_queue
|
||||
|
||||
with task_worker_lock:
|
||||
done_count = len(nodepack_result) + len(model_result)
|
||||
in_progress_count = len(tasks_in_progress)
|
||||
total_count = done_count + in_progress_count + task_queue.qsize()
|
||||
is_processing = task_worker_thread is not None and task_worker_thread.is_alive()
|
||||
if len(task_batch_queue) > 0:
|
||||
cur_batch = task_batch_queue[0]
|
||||
done_count = cur_batch.done_count()
|
||||
total_count = cur_batch.total_count()
|
||||
in_progress_count = len(tasks_in_progress)
|
||||
is_processing = task_worker_thread is not None and task_worker_thread.is_alive()
|
||||
else:
|
||||
done_count = 0
|
||||
total_count = 0
|
||||
in_progress_count = 0
|
||||
is_processing = False
|
||||
|
||||
return web.json_response({
|
||||
'total_count': total_count, 'done_count': done_count, 'in_progress_count': in_progress_count,
|
||||
'total_count': total_count,
|
||||
'done_count': done_count,
|
||||
'in_progress_count': in_progress_count,
|
||||
'is_processing': is_processing})
|
||||
|
||||
|
||||
@routes.post("/v2/manager/queue/install")
|
||||
async def install_custom_node(request):
|
||||
json_data = await request.json()
|
||||
print(f"install={json_data}")
|
||||
return await _install_custom_node(json_data)
|
||||
|
||||
|
||||
async def _install_custom_node(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
json_data = await request.json()
|
||||
|
||||
# non-nightly cnr is safe
|
||||
risky_level = None
|
||||
cnr_id = json_data.get('id')
|
||||
@ -1136,8 +1348,10 @@ async def install_custom_node(request):
|
||||
if json_data['version'] != 'unknown' and selected_version != 'unknown':
|
||||
if skip_post_install:
|
||||
if cnr_id in core.unified_manager.nightly_inactive_nodes or cnr_id in core.unified_manager.cnr_inactive_nodes:
|
||||
core.unified_manager.unified_enable(cnr_id)
|
||||
enable_item = json_data.get('ui_id'), cnr_id
|
||||
temp_queue_batch.append(("enable", enable_item))
|
||||
return web.Response(status=200)
|
||||
|
||||
elif selected_version is None:
|
||||
selected_version = 'latest'
|
||||
|
||||
@ -1150,9 +1364,11 @@ async def install_custom_node(request):
|
||||
if git_url is None:
|
||||
logging.error(f"[ComfyUI-Manager] Following node pack doesn't provide `nightly` version: ${git_url}")
|
||||
return web.Response(status=404, text=f"Following node pack doesn't provide `nightly` version: ${git_url}")
|
||||
|
||||
elif json_data['version'] != 'unknown' and selected_version == 'unknown':
|
||||
logging.error(f"[ComfyUI-Manager] Invalid installation request: {json_data}")
|
||||
return web.Response(status=400, text="Invalid installation request")
|
||||
|
||||
else:
|
||||
# unknown
|
||||
unknown_name = os.path.basename(json_data['files'][0])
|
||||
@ -1171,7 +1387,7 @@ async def install_custom_node(request):
|
||||
return web.Response(status=404, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
install_item = json_data.get('ui_id'), node_spec_str, json_data['channel'], json_data['mode'], skip_post_install
|
||||
task_queue.put(("install", install_item))
|
||||
temp_queue_batch.append(("install", install_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
@ -1180,16 +1396,16 @@ task_worker_thread:threading.Thread = None
|
||||
|
||||
@routes.get("/v2/manager/queue/start")
|
||||
async def queue_start(request):
|
||||
global nodepack_result
|
||||
global model_result
|
||||
with task_worker_lock:
|
||||
finalize_temp_queue_batch()
|
||||
return _queue_start()
|
||||
|
||||
def _queue_start():
|
||||
global task_worker_thread
|
||||
|
||||
|
||||
if task_worker_thread is not None and task_worker_thread.is_alive():
|
||||
return web.Response(status=201) # already in-progress
|
||||
|
||||
nodepack_result = {}
|
||||
model_result = {}
|
||||
|
||||
task_worker_thread = threading.Thread(target=lambda: asyncio.run(task_worker()))
|
||||
task_worker_thread.start()
|
||||
|
||||
@ -1198,12 +1414,15 @@ async def queue_start(request):
|
||||
|
||||
@routes.post("/v2/manager/queue/fix")
|
||||
async def fix_custom_node(request):
|
||||
json_data = await request.json()
|
||||
return await _fix_custom_node(json_data)
|
||||
|
||||
|
||||
async def _fix_custom_node(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_GENERAL)
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
json_data = await request.json()
|
||||
|
||||
node_id = json_data.get('id')
|
||||
node_ver = json_data['version']
|
||||
if node_ver != 'unknown':
|
||||
@ -1213,7 +1432,7 @@ async def fix_custom_node(request):
|
||||
node_name = os.path.basename(json_data['files'][0])
|
||||
|
||||
update_item = json_data.get('ui_id'), node_name, json_data['version']
|
||||
task_queue.put(("fix", update_item))
|
||||
temp_queue_batch.append(("fix", update_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
@ -1252,12 +1471,15 @@ async def install_custom_node_pip(request):
|
||||
|
||||
@routes.post("/v2/manager/queue/uninstall")
|
||||
async def uninstall_custom_node(request):
|
||||
json_data = await request.json()
|
||||
return await _uninstall_custom_node(json_data)
|
||||
|
||||
|
||||
async def _uninstall_custom_node(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
json_data = await request.json()
|
||||
|
||||
node_id = json_data.get('id')
|
||||
if json_data['version'] != 'unknown':
|
||||
is_unknown = False
|
||||
@ -1268,19 +1490,22 @@ async def uninstall_custom_node(request):
|
||||
node_name = os.path.basename(json_data['files'][0])
|
||||
|
||||
uninstall_item = json_data.get('ui_id'), node_name, is_unknown
|
||||
task_queue.put(("uninstall", uninstall_item))
|
||||
temp_queue_batch.append(("uninstall", uninstall_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@routes.post("/v2/manager/queue/update")
|
||||
async def update_custom_node(request):
|
||||
json_data = await request.json()
|
||||
return await _update_custom_node(json_data)
|
||||
|
||||
|
||||
async def _update_custom_node(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
json_data = await request.json()
|
||||
|
||||
node_id = json_data.get('id')
|
||||
if json_data['version'] != 'unknown':
|
||||
node_name = node_id
|
||||
@ -1289,7 +1514,7 @@ async def update_custom_node(request):
|
||||
node_name = os.path.basename(json_data['files'][0])
|
||||
|
||||
update_item = json_data.get('ui_id'), node_name, json_data['version']
|
||||
task_queue.put(("update", update_item))
|
||||
temp_queue_batch.append(("update", update_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
@ -1297,7 +1522,7 @@ async def update_custom_node(request):
|
||||
@routes.get("/v2/manager/queue/update_comfyui")
|
||||
async def update_comfyui(request):
|
||||
is_stable = core.get_config()['update_policy'] != 'nightly-comfyui'
|
||||
task_queue.put(("update-comfyui", ('comfyui', is_stable)))
|
||||
temp_queue_batch.append(("update-comfyui", ('comfyui', is_stable)))
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@ -1328,7 +1553,11 @@ async def comfyui_switch_version(request):
|
||||
@routes.post("/v2/manager/queue/disable")
|
||||
async def disable_node(request):
|
||||
json_data = await request.json()
|
||||
await _disable_node(json_data)
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
async def _disable_node(json_data):
|
||||
node_id = json_data.get('id')
|
||||
if json_data['version'] != 'unknown':
|
||||
is_unknown = False
|
||||
@ -1339,9 +1568,7 @@ async def disable_node(request):
|
||||
node_name = os.path.basename(json_data['files'][0])
|
||||
|
||||
update_item = json_data.get('ui_id'), node_name, is_unknown
|
||||
task_queue.put(("disable", update_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
temp_queue_batch.append(("disable", update_item))
|
||||
|
||||
|
||||
async def check_whitelist_for_model(item):
|
||||
@ -1363,7 +1590,10 @@ async def check_whitelist_for_model(item):
|
||||
@routes.post("/v2/manager/queue/install_model")
|
||||
async def install_model(request):
|
||||
json_data = await request.json()
|
||||
return await _install_model(json_data)
|
||||
|
||||
|
||||
async def _install_model(json_data):
|
||||
if not is_allowed_security_level('middle'):
|
||||
logging.error(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
@ -1387,7 +1617,7 @@ async def install_model(request):
|
||||
return web.Response(status=403, text="A security error has occurred. Please check the terminal logs")
|
||||
|
||||
install_item = json_data.get('ui_id'), json_data
|
||||
task_queue.put(("install-model", install_item))
|
||||
temp_queue_batch.append(("install-model", install_item))
|
||||
|
||||
return web.Response(status=200)
|
||||
|
||||
|
||||
@ -14,9 +14,9 @@ import { OpenArtShareDialog } from "./comfyui-share-openart.js";
|
||||
import {
|
||||
free_models, install_pip, install_via_git_url, manager_instance,
|
||||
rebootAPI, setManagerInstance, show_message, customAlert, customPrompt,
|
||||
infoToast, showTerminal, setNeedRestart
|
||||
infoToast, showTerminal, setNeedRestart, generateUUID
|
||||
} from "./common.js";
|
||||
import { ComponentBuilderDialog, getPureName, load_components, set_component_policy } from "./components-manager.js";
|
||||
import { ComponentBuilderDialog, load_components, set_component_policy } from "./components-manager.js";
|
||||
import { CustomNodesManager } from "./custom-nodes-manager.js";
|
||||
import { ModelManager } from "./model-manager.js";
|
||||
import { SnapshotManager } from "./snapshot.js";
|
||||
@ -232,7 +232,7 @@ var restart_stop_button = null;
|
||||
var update_policy_combo = null;
|
||||
|
||||
let share_option = 'all';
|
||||
var is_updating = false;
|
||||
var batch_id = null;
|
||||
|
||||
|
||||
// copied style from https://github.com/pythongosssss/ComfyUI-Custom-Scripts
|
||||
@ -474,14 +474,19 @@ async function updateComfyUI() {
|
||||
let prev_text = update_comfyui_button.innerText;
|
||||
update_comfyui_button.innerText = "Updating ComfyUI...";
|
||||
|
||||
set_inprogress_mode();
|
||||
|
||||
const response = await api.fetchApi('/v2/manager/queue/update_comfyui');
|
||||
|
||||
// set_inprogress_mode();
|
||||
showTerminal();
|
||||
|
||||
batch_id = generateUUID();
|
||||
|
||||
let batch = {};
|
||||
batch['batch_id'] = batch_id;
|
||||
batch['update_comfyui'] = true;
|
||||
|
||||
is_updating = true;
|
||||
await api.fetchApi('/v2/manager/queue/start');
|
||||
const res = await api.fetchApi(`/v2/manager/queue/batch`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(batch)
|
||||
});
|
||||
}
|
||||
|
||||
function showVersionSelectorDialog(versions, current, onSelect) {
|
||||
@ -656,18 +661,17 @@ async function onQueueStatus(event) {
|
||||
const isElectron = 'electronAPI' in window;
|
||||
|
||||
if(event.detail.status == 'in_progress') {
|
||||
set_inprogress_mode();
|
||||
// set_inprogress_mode();
|
||||
update_all_button.innerText = `in progress.. (${event.detail.done_count}/${event.detail.total_count})`;
|
||||
}
|
||||
else if(event.detail.status == 'done') {
|
||||
reset_action_buttons();
|
||||
|
||||
if(!is_updating) {
|
||||
else if(event.detail.status == 'all-done') {
|
||||
// reset_action_buttons();
|
||||
}
|
||||
else if(event.detail.status == 'batch-done') {
|
||||
if(batch_id != event.detail.batch_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_updating = false;
|
||||
|
||||
|
||||
let success_list = [];
|
||||
let failed_list = [];
|
||||
let comfyui_state = null;
|
||||
@ -767,41 +771,28 @@ api.addEventListener("cm-queue-status", onQueueStatus);
|
||||
async function updateAll(update_comfyui) {
|
||||
update_all_button.innerText = "Updating...";
|
||||
|
||||
set_inprogress_mode();
|
||||
// set_inprogress_mode();
|
||||
|
||||
var mode = manager_instance.datasrc_combo.value;
|
||||
|
||||
showTerminal();
|
||||
|
||||
batch_id = generateUUID();
|
||||
|
||||
let batch = {};
|
||||
if(update_comfyui) {
|
||||
update_all_button.innerText = "Updating ComfyUI...";
|
||||
await api.fetchApi('/v2/manager/queue/update_comfyui');
|
||||
batch['update_comfyui'] = true;
|
||||
}
|
||||
|
||||
const response = await api.fetchApi(`/v2/manager/queue/update_all?mode=${mode}`);
|
||||
batch['update_all'] = mode;
|
||||
|
||||
if (response.status == 401) {
|
||||
customAlert('Another task is already in progress. Please stop the ongoing task first.');
|
||||
}
|
||||
else if(response.status == 200) {
|
||||
is_updating = true;
|
||||
await api.fetchApi('/v2/manager/queue/start');
|
||||
}
|
||||
const res = await api.fetchApi(`/v2/manager/queue/batch`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(batch)
|
||||
});
|
||||
}
|
||||
|
||||
function newDOMTokenList(initialTokens) {
|
||||
const tmp = document.createElement(`div`);
|
||||
|
||||
const classList = tmp.classList;
|
||||
if (initialTokens) {
|
||||
initialTokens.forEach(token => {
|
||||
classList.add(token);
|
||||
});
|
||||
}
|
||||
|
||||
return classList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the node is a potential output node (img, gif or video output)
|
||||
*/
|
||||
|
||||
@ -630,6 +630,14 @@ export function showTooltip(target, text, className = 'cn-tooltip', styleMap = {
|
||||
});
|
||||
}
|
||||
|
||||
export function generateUUID() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
const r = Math.random() * 16 | 0;
|
||||
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
function initTooltip () {
|
||||
const mouseenterHandler = (e) => {
|
||||
const target = e.target;
|
||||
|
||||
@ -7,7 +7,7 @@ import {
|
||||
fetchData, md5, icons, show_message, customConfirm, customAlert, customPrompt,
|
||||
sanitizeHTML, infoToast, showTerminal, setNeedRestart,
|
||||
storeColumnWidth, restoreColumnWidth, getTimeAgo, copyText, loadCss,
|
||||
showPopover, hidePopover
|
||||
showPopover, hidePopover, generateUUID
|
||||
} from "./common.js";
|
||||
|
||||
// https://cenfun.github.io/turbogrid/api.html
|
||||
@ -1440,13 +1440,6 @@ export class CustomNodesManager {
|
||||
}
|
||||
|
||||
async installNodes(list, btn, title, selected_version) {
|
||||
let stats = await api.fetchApi('/v2/manager/queue/status');
|
||||
stats = await stats.json();
|
||||
if(stats.is_processing) {
|
||||
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
|
||||
return;
|
||||
}
|
||||
|
||||
const { target, label, mode} = btn;
|
||||
|
||||
if(mode === "uninstall") {
|
||||
@ -1473,10 +1466,10 @@ export class CustomNodesManager {
|
||||
let needRestart = false;
|
||||
let errorMsg = "";
|
||||
|
||||
await api.fetchApi('/v2/manager/queue/reset');
|
||||
|
||||
let target_items = [];
|
||||
|
||||
let batch = {};
|
||||
|
||||
for (const hash of list) {
|
||||
const item = this.grid.getRowItemBy("hash", hash);
|
||||
target_items.push(item);
|
||||
@ -1518,23 +1511,11 @@ export class CustomNodesManager {
|
||||
api_mode = 'reinstall';
|
||||
}
|
||||
|
||||
const res = await api.fetchApi(`/v2/manager/queue/${api_mode}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.status != 200) {
|
||||
errorMsg = `'${item.title}': `;
|
||||
|
||||
if(res.status == 403) {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
} else if(res.status == 404) {
|
||||
errorMsg += `With the current security level configuration, only custom nodes from the <B>"default channel"</B> can be installed.\n`;
|
||||
} else {
|
||||
errorMsg += await res.text() + '\n';
|
||||
}
|
||||
|
||||
break;
|
||||
if(batch[api_mode]) {
|
||||
batch[api_mode].push(data);
|
||||
}
|
||||
else {
|
||||
batch[api_mode] = [data];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1551,7 +1532,24 @@ export class CustomNodesManager {
|
||||
}
|
||||
}
|
||||
else {
|
||||
await api.fetchApi('/v2/manager/queue/start');
|
||||
this.batch_id = generateUUID();
|
||||
batch['batch_id'] = this.batch_id;
|
||||
|
||||
const res = await api.fetchApi(`/v2/manager/queue/batch`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(batch)
|
||||
});
|
||||
|
||||
let failed = await res.json();
|
||||
|
||||
if(failed.length > 0) {
|
||||
for(let k in failed) {
|
||||
let hash = failed[k].ui_id;
|
||||
const item = this.grid.getRowItemBy("hash", hash);
|
||||
errorMsg = `[FAIL] ${item.title}`;
|
||||
}
|
||||
}
|
||||
|
||||
this.showStop();
|
||||
showTerminal();
|
||||
}
|
||||
@ -1569,7 +1567,7 @@ export class CustomNodesManager {
|
||||
self.grid.updateCell(item, "action");
|
||||
self.grid.setRowSelected(item, false);
|
||||
}
|
||||
else if(event.detail.status == 'done') {
|
||||
else if(event.detail.status == 'batch-done' && event.detail.batch_id == self.batch_id) {
|
||||
self.hideStop();
|
||||
self.onQueueCompleted(event.detail);
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import { $el } from "../../scripts/ui.js";
|
||||
import {
|
||||
manager_instance, rebootAPI,
|
||||
fetchData, md5, icons, show_message, customAlert, infoToast, showTerminal,
|
||||
storeColumnWidth, restoreColumnWidth, loadCss
|
||||
storeColumnWidth, restoreColumnWidth, loadCss, generateUUID
|
||||
} from "./common.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
|
||||
@ -435,24 +435,16 @@ export class ModelManager {
|
||||
}
|
||||
|
||||
async installModels(list, btn) {
|
||||
let stats = await api.fetchApi('/v2/manager/queue/status');
|
||||
|
||||
stats = await stats.json();
|
||||
if(stats.is_processing) {
|
||||
customAlert(`[ComfyUI-Manager] There are already tasks in progress. Please try again after it is completed. (${stats.done_count}/${stats.total_count})`);
|
||||
return;
|
||||
}
|
||||
|
||||
btn.classList.add("cmm-btn-loading");
|
||||
this.showError("");
|
||||
|
||||
let needRefresh = false;
|
||||
let errorMsg = "";
|
||||
|
||||
await api.fetchApi('/v2/manager/queue/reset');
|
||||
|
||||
let target_items = [];
|
||||
|
||||
let batch = {};
|
||||
|
||||
for (const item of list) {
|
||||
this.grid.scrollRowIntoView(item);
|
||||
target_items.push(item);
|
||||
@ -468,21 +460,12 @@ export class ModelManager {
|
||||
const data = item.originalData;
|
||||
data.ui_id = item.hash;
|
||||
|
||||
const res = await api.fetchApi(`/v2/manager/queue/install_model`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.status != 200) {
|
||||
errorMsg = `'${item.name}': `;
|
||||
|
||||
if(res.status == 403) {
|
||||
errorMsg += `This action is not allowed with this security level configuration.\n`;
|
||||
} else {
|
||||
errorMsg += await res.text() + '\n';
|
||||
}
|
||||
|
||||
break;
|
||||
if(batch['install_model']) {
|
||||
batch['install_model'].push(data);
|
||||
}
|
||||
else {
|
||||
batch['install_model'] = [data];
|
||||
}
|
||||
}
|
||||
|
||||
@ -499,7 +482,24 @@ export class ModelManager {
|
||||
}
|
||||
}
|
||||
else {
|
||||
await api.fetchApi('/v2/manager/queue/start');
|
||||
this.batch_id = generateUUID();
|
||||
batch['batch_id'] = this.batch_id;
|
||||
|
||||
const res = await api.fetchApi(`/v2/manager/queue/batch`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(batch)
|
||||
});
|
||||
|
||||
let failed = await res.json();
|
||||
|
||||
if(failed.length > 0) {
|
||||
for(let k in failed) {
|
||||
let hash = failed[k].ui_id;
|
||||
const item = self.grid.getRowItemBy("hash", hash);
|
||||
errorMsg = `[FAIL] ${item.title}`;
|
||||
}
|
||||
}
|
||||
|
||||
this.showStop();
|
||||
showTerminal();
|
||||
}
|
||||
@ -519,7 +519,7 @@ export class ModelManager {
|
||||
// self.grid.updateCell(item, "tg-column-select");
|
||||
self.grid.updateRow(item);
|
||||
}
|
||||
else if(event.detail.status == 'done') {
|
||||
else if(event.detail.status == 'batch-done') {
|
||||
self.hideStop();
|
||||
self.onQueueCompleted(event.detail);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user