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:
Dariusz L
2026-08-03 19:51:42 +02:00
parent dcb4996333
commit a431723b7d
2 changed files with 59 additions and 7 deletions
+7 -7
View File
@@ -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)
+52
View File
@@ -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")