Skip to content

Commit 9f0d3be

Browse files
authored
Merge pull request #6582 from opsmill/ajtm-06012025-diff-save-query-update
update cypher query to use less memory
2 parents 1d575ff + 1cb2124 commit 9f0d3be

File tree

2 files changed

+76
-45
lines changed

2 files changed

+76
-45
lines changed

backend/infrahub/core/diff/query/save.py

Lines changed: 75 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def __init__(self, node_create_batch: list[EnrichedNodeCreateRequest], **kwargs:
8080

8181
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
8282
self.params = self._build_node_batch_params()
83+
8384
query = """
8485
UNWIND $node_details_list AS node_details
8586
WITH
@@ -136,65 +137,82 @@ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa
136137
OPTIONAL MATCH (diff_node)-[:DIFF_HAS_CONFLICT]->(node_conflict:DiffConflict)
137138
SET node_conflict = node_conflict_params
138139
}
140+
// -------------------------
141+
// resetting the UNWIND and starting over here reduces memory usage
142+
// -------------------------
143+
WITH root_uuid LIMIT 1
144+
UNWIND $node_details_list AS node_details
145+
WITH
146+
node_details.root_uuid AS root_uuid,
147+
node_details.node_map AS node_map,
148+
toString(node_details.node_map.node_properties.uuid) AS node_uuid,
149+
node_details.node_map.node_properties.db_id AS node_db_id
150+
MATCH (:DiffRoot {uuid: root_uuid})-[:DIFF_HAS_NODE]->(diff_node:DiffNode {uuid: node_uuid, db_id: node_db_id})
151+
WITH diff_node, node_map, %(attr_name_list_comp)s AS attr_names
152+
OPTIONAL MATCH (diff_node)-[:DIFF_HAS_ATTRIBUTE]->(attr_to_delete:DiffAttribute)
153+
WHERE NOT (attr_to_delete.name IN attr_names)
154+
OPTIONAL MATCH (attr_to_delete)-[*..6]->(next_to_delete)
155+
DETACH DELETE next_to_delete
156+
DETACH DELETE attr_to_delete
157+
// -------------------------
158+
// add attributes for this node
159+
// -------------------------
160+
WITH DISTINCT diff_node, node_map
139161
CALL {
140-
// -------------------------
141-
// remove stale attributes for this node
142-
// -------------------------
143162
WITH diff_node, node_map
144-
CALL {
145-
WITH diff_node, node_map
146-
WITH diff_node, %(attr_name_list_comp)s AS attr_names
147-
OPTIONAL MATCH (diff_node)-[:DIFF_HAS_ATTRIBUTE]->(attr_to_delete:DiffAttribute)
148-
WHERE NOT (attr_to_delete.name IN attr_names)
149-
OPTIONAL MATCH (attr_to_delete)-[*..6]->(next_to_delete)
150-
DETACH DELETE next_to_delete
151-
DETACH DELETE attr_to_delete
152-
}
153-
// -------------------------
154-
// add attributes for this node
155-
// -------------------------
156163
UNWIND node_map.attributes AS node_attribute
157164
MERGE (diff_node)-[:DIFF_HAS_ATTRIBUTE]->(diff_attribute:DiffAttribute {name: node_attribute.node_properties.name})
158165
SET diff_attribute = node_attribute.node_properties
159166
// -------------------------
160-
// add properties for this attribute
167+
// remove stale properties for this attribute
161168
// -------------------------
162-
WITH diff_attribute, node_attribute
169+
WITH diff_attribute, node_attribute, %(attr_props_list_comp)s AS prop_types
170+
OPTIONAL MATCH (diff_attribute)-[:DIFF_HAS_PROPERTY]->(prop_to_delete:DiffProperty)
171+
WHERE NOT (prop_to_delete.property_type IN prop_types)
172+
OPTIONAL MATCH (prop_to_delete)-[*..4]->(next_to_delete)
173+
DETACH DELETE next_to_delete
174+
DETACH DELETE prop_to_delete
163175
// -------------------------
164-
// remove stale properties for this attribute
176+
// set attribute property values
165177
// -------------------------
166-
CALL {
167-
WITH diff_attribute, node_attribute
168-
WITH diff_attribute, %(attr_props_list_comp)s AS prop_types
169-
OPTIONAL MATCH (diff_attribute)-[:DIFF_HAS_PROPERTY]->(prop_to_delete:DiffProperty)
170-
WHERE NOT (prop_to_delete.property_type IN prop_types)
171-
OPTIONAL MATCH (prop_to_delete)-[*..4]->(next_to_delete)
172-
DETACH DELETE next_to_delete
173-
DETACH DELETE prop_to_delete
174-
}
178+
WITH DISTINCT diff_attribute, node_attribute
175179
UNWIND node_attribute.properties AS attr_property
176180
MERGE (diff_attribute)-[:DIFF_HAS_PROPERTY]->(diff_attr_prop:DiffProperty {property_type: attr_property.node_properties.property_type})
177181
SET diff_attr_prop = attr_property.node_properties
178-
// -------------------------
179-
// add/remove conflict for this property
180-
// -------------------------
181182
WITH diff_attr_prop, attr_property
182183
OPTIONAL MATCH (diff_attr_prop)-[:DIFF_HAS_CONFLICT]->(current_attr_prop_conflict:DiffConflict)
183184
WITH diff_attr_prop, attr_property, current_attr_prop_conflict, (attr_property.conflict_params IS NOT NULL) AS has_prop_conflict
184-
FOREACH (i in CASE WHEN has_prop_conflict = FALSE THEN [1] ELSE [] END |
185+
CALL {
186+
WITH has_prop_conflict, current_attr_prop_conflict
187+
WITH has_prop_conflict, current_attr_prop_conflict
188+
WHERE has_prop_conflict = FALSE AND current_attr_prop_conflict IS NOT NULL
185189
DETACH DELETE current_attr_prop_conflict
186-
)
187-
FOREACH (i in CASE WHEN has_prop_conflict = TRUE THEN [1] ELSE [] END |
190+
}
191+
CALL {
192+
WITH has_prop_conflict, diff_attr_prop, attr_property
193+
WITH has_prop_conflict, diff_attr_prop, attr_property
194+
WHERE has_prop_conflict = TRUE
188195
MERGE (diff_attr_prop)-[:DIFF_HAS_CONFLICT]->(diff_attr_prop_conflict:DiffConflict)
189196
SET diff_attr_prop_conflict = attr_property.conflict_params
190-
)
197+
}
191198
}
192199
// -------------------------
200+
// resetting the UNWIND and starting over here reduces memory usage
201+
// -------------------------
202+
WITH 1 AS resetting LIMIT 1
203+
UNWIND $node_details_list AS node_details
204+
WITH
205+
node_details.root_uuid AS root_uuid,
206+
node_details.node_map AS node_map,
207+
toString(node_details.node_map.node_properties.uuid) AS node_uuid,
208+
node_details.node_map.node_properties.db_id AS node_db_id
209+
MATCH (:DiffRoot {uuid: root_uuid})-[:DIFF_HAS_NODE]->(diff_node:DiffNode {uuid: node_uuid, db_id: node_db_id})
210+
// -------------------------
193211
// remove stale relationships for this node
194212
// -------------------------
195213
CALL {
196214
WITH diff_node, node_map
197-
WITH diff_node, %(rel_name_list_comp)s AS rel_names
215+
WITH diff_node, node_map, %(rel_name_list_comp)s AS rel_names
198216
OPTIONAL MATCH (diff_node)-[:DIFF_HAS_RELATIONSHIP]->(rel_to_delete:DiffRelationship)
199217
WHERE NOT (rel_to_delete.name IN rel_names)
200218
OPTIONAL MATCH (rel_to_delete)-[*..8]->(next_to_delete)
@@ -214,7 +232,7 @@ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa
214232
WITH diff_relationship, node_relationship
215233
CALL {
216234
WITH diff_relationship, node_relationship
217-
WITH diff_relationship, %(rel_peers_list_comp)s AS rel_peers
235+
WITH diff_relationship, node_relationship, %(rel_peers_list_comp)s AS rel_peers
218236
OPTIONAL MATCH (diff_relationship)-[:DIFF_HAS_ELEMENT]->(element_to_delete:DiffRelationshipElement)
219237
WHERE NOT (element_to_delete.peer_id IN rel_peers)
220238
OPTIONAL MATCH (element_to_delete)-[*..6]->(next_to_delete)
@@ -236,20 +254,26 @@ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa
236254
OPTIONAL MATCH (diff_relationship_element)-[:DIFF_HAS_CONFLICT]->(current_element_conflict:DiffConflict)
237255
WITH diff_relationship_element, node_single_relationship, current_element_conflict,
238256
(node_single_relationship.conflict_params IS NOT NULL) AS has_element_conflict
239-
FOREACH (i in CASE WHEN has_element_conflict = FALSE THEN [1] ELSE [] END |
257+
CALL {
258+
WITH has_element_conflict, current_element_conflict
259+
WITH has_element_conflict, current_element_conflict
260+
WHERE has_element_conflict = FALSE
240261
DETACH DELETE current_element_conflict
241-
)
242-
FOREACH (i in CASE WHEN has_element_conflict = TRUE THEN [1] ELSE [] END |
262+
}
263+
CALL {
264+
WITH has_element_conflict, diff_relationship_element, node_single_relationship
265+
WITH has_element_conflict, diff_relationship_element, node_single_relationship
266+
WHERE has_element_conflict = TRUE
243267
MERGE (diff_relationship_element)-[:DIFF_HAS_CONFLICT]->(element_conflict:DiffConflict)
244268
SET element_conflict = node_single_relationship.conflict_params
245-
)
269+
}
246270
// -------------------------
247271
// remove stale properties for this relationship element
248272
// -------------------------
249273
WITH diff_relationship_element, node_single_relationship
250274
CALL {
251275
WITH diff_relationship_element, node_single_relationship
252-
WITH diff_relationship_element, %(element_props_list_comp)s AS element_props
276+
WITH diff_relationship_element, node_single_relationship, %(element_props_list_comp)s AS element_props
253277
OPTIONAL MATCH (diff_relationship_element)-[:DIFF_HAS_PROPERTY]->(property_to_delete:DiffProperty)
254278
WHERE NOT (property_to_delete.property_type IN element_props)
255279
OPTIONAL MATCH (property_to_delete)-[*..4]->(next_to_delete)
@@ -271,13 +295,19 @@ async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa
271295
OPTIONAL MATCH (diff_relationship_property)-[:DIFF_HAS_CONFLICT]->(diff_relationship_property_conflict:DiffConflict)
272296
WITH diff_relationship_property, node_relationship_property, diff_relationship_property_conflict,
273297
(node_relationship_property.conflict_params IS NOT NULL) AS has_property_conflict
274-
FOREACH (i in CASE WHEN has_property_conflict = FALSE THEN [1] ELSE [] END |
298+
CALL {
299+
WITH has_property_conflict, diff_relationship_property_conflict
300+
WITH has_property_conflict, diff_relationship_property_conflict
301+
WHERE has_property_conflict = FALSE
275302
DETACH DELETE diff_relationship_property_conflict
276-
)
277-
FOREACH (i in CASE WHEN has_property_conflict = TRUE THEN [1] ELSE [] END |
303+
}
304+
CALL {
305+
WITH has_property_conflict, diff_relationship_property, node_relationship_property
306+
WITH has_property_conflict, diff_relationship_property, node_relationship_property
307+
WHERE has_property_conflict = TRUE
278308
MERGE (diff_relationship_property)-[:DIFF_HAS_CONFLICT]->(property_conflict:DiffConflict)
279309
SET property_conflict = node_relationship_property.conflict_params
280-
)
310+
}
281311
""" % {
282312
"attr_name_list_comp": db.render_list_comprehension(
283313
items="node_map.attributes", item_name="node_properties.name"

changelog/6568.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Update the cypher query that saves a diff to use less memory.

0 commit comments

Comments
 (0)