fix: preserve promoted context cache when inner subgraph widgets change
Previously, _get_promoted_widget_context_cache_key included widgets_values from context nodes, so changing a widget inside a promoted subgraph invalidated the entire cache snapshot even when promotion topology and other nodes were unchanged. This makes promoted-context snapshots key off node structure and topology only, while individual nodes are still reanalyzed when their widgets_values actually change.
This commit is contained in:
@@ -159,14 +159,14 @@ def _get_promoted_widget_context_cache_key(
|
||||
for node in nodes:
|
||||
if not isinstance(node, dict):
|
||||
continue
|
||||
widgets_values = node.get("widgets_values", [])
|
||||
context_node = {
|
||||
**node,
|
||||
"widgets_values": (
|
||||
list(widgets_values)
|
||||
if isinstance(widgets_values, list)
|
||||
else []
|
||||
),
|
||||
# Inner widget values are part of each node fingerprint
|
||||
# and must not invalidate the whole promoted-context
|
||||
# snapshot. The current node is reanalyzed when its value
|
||||
# changes, while promotion topology is rebuilt below.
|
||||
key: value
|
||||
for key, value in node.items()
|
||||
if key != "widgets_values"
|
||||
}
|
||||
context_nodes.append(
|
||||
_normalize_workflow_analysis_value(context_node)
|
||||
|
||||
@@ -1626,6 +1626,58 @@ class WorkflowModelInventoryCacheTests(unittest.TestCase):
|
||||
|
||||
self.assertEqual(6, get_node_info.call_count)
|
||||
|
||||
def test_inner_subgraph_model_change_reuses_unchanged_nodes(self):
|
||||
def build_workflow(inner_value):
|
||||
return {
|
||||
"nodes": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "subgraph-1",
|
||||
"widgets_values": [],
|
||||
"properties": {},
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"subgraphs": [
|
||||
{
|
||||
"id": "subgraph-1",
|
||||
"name": "Model subgraph",
|
||||
"inputs": [],
|
||||
"nodes": [
|
||||
{
|
||||
**_workflow_with_model(inner_value)["nodes"][0],
|
||||
"id": 10,
|
||||
},
|
||||
{
|
||||
**_workflow_with_model(
|
||||
"unchanged.safetensors"
|
||||
)["nodes"][0],
|
||||
"id": 11,
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
with (
|
||||
patch(
|
||||
"core.scanner.get_model_files",
|
||||
return_value=[],
|
||||
),
|
||||
patch.object(
|
||||
references,
|
||||
"get_node_model_info",
|
||||
wraps=references.get_node_model_info,
|
||||
) as get_node_info,
|
||||
):
|
||||
get_workflow_model_inventory(build_workflow("first.safetensors"))
|
||||
get_workflow_model_inventory(build_workflow("second.safetensors"))
|
||||
|
||||
self.assertEqual(4, get_node_info.call_count)
|
||||
|
||||
def test_scanner_invalidation_clears_shared_inventory(self):
|
||||
workflow = _workflow_with_model("invalidated.safetensors")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user