Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix+optimize #111

Merged
merged 1 commit into from
Oct 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 67 additions & 51 deletions src/lifeblood/scheduler_ui_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import pickle
import json
import asyncio
import time
from asyncio.exceptions import IncompleteReadError
from . import logging
from .attribute_serialization import serialize_attributes_core, deserialize_attributes_core
Expand Down Expand Up @@ -326,55 +327,65 @@ async def comm_set_node_params(): # elif command == b'batchsetnodeparams':
return_values: Dict[str, Tuple[bool, Optional[Tuple[NodeParameterType, Union[float, int, bool, str]]]]] = {} # list of param_names to [set success?, final value]
async with self.__scheduler.node_object_by_id_for_writing(node_id) as node:
node: BaseNode
cycle_start = None
something_was_set_last_loop = False
for param_name, param_type, value_is_expression, param_value in stuff_to_set:
try:
await asyncio.get_event_loop().run_in_executor(None, node.param, param_name)
except ParameterNotFound:
# some parameters may only be present after other parameters are set.
# for example - multigroup element will appear only after count is set
# so we postpone setting missing parameters
# and only consider it a failure if no more parameters can be found at all
if cycle_start is None or cycle_start == param_name and something_was_set_last_loop:
cycle_start = param_name
something_was_set_last_loop = False
stuff_to_set.append((param_name, param_type, value_is_expression, param_value)) # put back
else: # means we already checked all parameters since last successful set and set nothing new
self.__logger.warning(f'failed request to set node {node_id} parameter "{param_name}" - parameter not found')
return_values[param_name] = (False, None)
continue
try:
def _set_helper(node: "BaseNode", param_name: str, value_is_expression: bool, value: Union[float, int, bool, str]):
param = node.param(param_name)
if value_is_expression:
param.set_expression(param_value)
else:
if param.has_expression():
param.set_expression(None)
param.set_value(value)

await asyncio.get_event_loop().run_in_executor(None, _set_helper, node, param_name, value_is_expression, param_value)
something_was_set_last_loop = True
value = node.param(param_name).unexpanded_value()
except ParameterReadonly:
self.__logger.warning(f'failed request to set node {node_id} parameter "{param_name}"({NodeParameterType(param_type).name}). parameter is READ ONLY')
return_values[param_name] = (False, None)
except ParameterLocked:
self.__logger.warning(f'failed request to set node {node_id} parameter "{param_name}"({NodeParameterType(param_type).name}). parameter is LOCKED')
return_values[param_name] = (False, None)
except ParameterCannotHaveExpressions:
self.__logger.warning(f'failed request to set node {node_id} parameter "{param_name}" expression. parameter cannot have expressions')
return_values[param_name] = (False, None)
except Exception as e:
err_val_prev = str(param_value)
if len(err_val_prev) > 23:
err_val_prev = err_val_prev[:20] + '...'
self.__logger.warning(f'FAILED request to set node {node_id} parameter "{param_name}"({NodeParameterType(param_type).name}) to {err_val_prev}')
self.__logger.exception(e)
return_values[param_name] = (False, None)
else: # all went well, parameter was set
return_values[param_name] = (True, (param_type, value))

def _set_batch_helper(
node: "BaseNode",
stuff_to_set: List[Tuple[str, NodeParameterType, bool, Union[float, int, bool, str]]],
return_values: Dict[str, Tuple[bool, Optional[Tuple[NodeParameterType, Union[float, int, bool, str]]]]],
):
cycle_start = None
something_was_set_last_loop = False
cycle_failed = False
with node.get_ui().postpone_ui_callbacks():
for param_name, param_type, value_is_expression, param_value in stuff_to_set:
try:
param = node.param(param_name)
if value_is_expression:
param.set_expression(param_value)
else:
if param.has_expression():
param.set_expression(None)
param.set_value(param_value)

something_was_set_last_loop = True
value = node.param(param_name).unexpanded_value()
except ParameterNotFound:
# some parameters may only be present after other parameters are set.
# for example - multigroup element will appear only after count is set,
# so we postpone setting missing parameters
# and only consider it a failure if no more parameters can be found at all
if not cycle_failed and cycle_start == param_name and not something_was_set_last_loop:
cycle_failed = True
elif cycle_start is None or cycle_start == param_name and something_was_set_last_loop:
cycle_start = param_name
something_was_set_last_loop = False

if not cycle_failed:
stuff_to_set.append((param_name, param_type, value_is_expression, param_value)) # put back
else: # means we already checked all parameters since last successful set and set nothing new
self.__logger.warning(f'failed request to set node {node_id} parameter "{param_name}" - parameter not found')
return_values[param_name] = (False, None)
continue
except ParameterReadonly:
self.__logger.warning(f'failed request to set node {node_id} parameter "{param_name}"({NodeParameterType(param_type).name}). parameter is READ ONLY')
return_values[param_name] = (False, None)
except ParameterLocked:
self.__logger.warning(f'failed request to set node {node_id} parameter "{param_name}"({NodeParameterType(param_type).name}). parameter is LOCKED')
return_values[param_name] = (False, None)
except ParameterCannotHaveExpressions:
self.__logger.warning(f'failed request to set node {node_id} parameter "{param_name}" expression. parameter cannot have expressions')
return_values[param_name] = (False, None)
except Exception as e:
err_val_prev = str(param_value)
if len(err_val_prev) > 23:
err_val_prev = err_val_prev[:20] + '...'
self.__logger.warning(f'FAILED request to set node {node_id} parameter "{param_name}"({NodeParameterType(param_type).name}) to {err_val_prev}')
self.__logger.exception(e)
return_values[param_name] = (False, None)
else: # all went well, parameter was set
return_values[param_name] = (True, (param_type, value))

await asyncio.get_event_loop().run_in_executor(None, _set_batch_helper, node, stuff_to_set, return_values)

if not want_result:
writer.write(b'\1')
Expand Down Expand Up @@ -695,11 +706,16 @@ async def write_string(s: str):
except IncompleteReadError: # this means connection was closed
self.__logger.debug('UI disconnected: connection closed')
break
self.__logger.debug(f'got command {command}')
self.__logger.debug(f'got command %s', command)
# get full nodegraph state. only brings in where is which item, no other details

if command in commands:
await commands[command]()
if self.__logger.isEnabledFor(logging.DEBUG):
benchmark_start = time.perf_counter()
await commands[command]()
self.__logger.debug('command %s took %.4f', command, time.perf_counter() - benchmark_start)
else:
await commands[command]()
#
# if conn is closed - result will be b'', but in mostl likely totally impossible case it can be unfinished command.
# so lets just catch all
Expand Down
Loading