Skip to content

Commit 78b4523

Browse files
authored
refactor diff calculation query to get less information (#4376)
* IFC-580 refactor diff calculation query to get less information * changes to support memgraph * link base and diff branch diffs more strongly * put all the pieces together * format * fix save query for memgraph * fix some more bugs and add tests * neo4j typo, one more unit test * add a "migration" to delete all diffs b/c of the new format * add newsfragment
1 parent 5b7da78 commit 78b4523

File tree

26 files changed

+1544
-890
lines changed

26 files changed

+1544
-890
lines changed

backend/infrahub/core/diff/calculator.py

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,64 @@
55
from infrahub.core.timestamp import Timestamp
66
from infrahub.database import InfrahubDatabase
77

8-
from .model.path import CalculatedDiffs
8+
from .model.path import CalculatedDiffs, NodeFieldSpecifier
99

1010

1111
class DiffCalculator:
1212
def __init__(self, db: InfrahubDatabase) -> None:
1313
self.db = db
1414

1515
async def calculate_diff(
16-
self, base_branch: Branch, diff_branch: Branch, from_time: Timestamp, to_time: Timestamp
16+
self,
17+
base_branch: Branch,
18+
diff_branch: Branch,
19+
from_time: Timestamp,
20+
to_time: Timestamp,
21+
previous_node_specifiers: set[NodeFieldSpecifier] | None = None,
1722
) -> CalculatedDiffs:
18-
diff_query = await DiffAllPathsQuery.init(
23+
if diff_branch.name == registry.default_branch:
24+
diff_branch_create_time = from_time
25+
else:
26+
diff_branch_create_time = Timestamp(diff_branch.get_created_at())
27+
diff_parser = DiffQueryParser(
28+
base_branch=base_branch,
29+
diff_branch=diff_branch,
30+
schema_manager=registry.schema,
31+
from_time=from_time,
32+
to_time=to_time,
33+
)
34+
branch_diff_query = await DiffAllPathsQuery.init(
1935
db=self.db,
2036
branch=diff_branch,
2137
base_branch=base_branch,
38+
diff_branch_create_time=diff_branch_create_time,
2239
diff_from=from_time,
2340
diff_to=to_time,
2441
)
25-
await diff_query.execute(db=self.db)
26-
diff_parser = DiffQueryParser(
27-
diff_query=diff_query,
28-
base_branch_name=base_branch.name,
29-
diff_branch_name=diff_branch.name,
30-
schema_manager=registry.schema,
31-
from_time=from_time,
32-
to_time=to_time,
33-
)
42+
await branch_diff_query.execute(db=self.db)
43+
for query_result in branch_diff_query.get_results():
44+
diff_parser.read_result(query_result=query_result)
45+
46+
if base_branch.name != diff_branch.name:
47+
branch_node_specifiers = diff_parser.get_node_field_specifiers_for_branch(branch_name=diff_branch.name)
48+
new_node_field_specifiers = branch_node_specifiers - (previous_node_specifiers or set())
49+
current_node_field_specifiers = (previous_node_specifiers or set()) - new_node_field_specifiers
50+
base_diff_query = await DiffAllPathsQuery.init(
51+
db=self.db,
52+
branch=base_branch,
53+
base_branch=base_branch,
54+
diff_branch_create_time=diff_branch_create_time,
55+
diff_from=from_time,
56+
diff_to=to_time,
57+
current_node_field_specifiers=[
58+
(nfs.node_uuid, nfs.field_name) for nfs in current_node_field_specifiers
59+
],
60+
new_node_field_specifiers=[(nfs.node_uuid, nfs.field_name) for nfs in new_node_field_specifiers],
61+
)
62+
await base_diff_query.execute(db=self.db)
63+
for query_result in base_diff_query.get_results():
64+
diff_parser.read_result(query_result=query_result)
65+
3466
diff_parser.parse()
3567
return CalculatedDiffs(
3668
base_branch_name=base_branch.name,

backend/infrahub/core/diff/combiner.py

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
EnrichedDiffProperty,
1414
EnrichedDiffRelationship,
1515
EnrichedDiffRoot,
16+
EnrichedDiffs,
1617
EnrichedDiffSingleRelationship,
1718
)
1819

@@ -356,16 +357,33 @@ def _link_child_nodes(self, nodes: Iterable[EnrichedDiffNode]) -> None:
356357
parent_rel = child_node.get_relationship(name=parent_rel_name)
357358
parent_rel.nodes.add(parent_node)
358359

359-
async def combine(self, earlier_diff: EnrichedDiffRoot, later_diff: EnrichedDiffRoot) -> EnrichedDiffRoot:
360-
self._initialize(earlier_diff=earlier_diff, later_diff=later_diff)
361-
filtered_node_pairs = self._filter_nodes_to_keep(earlier_diff=earlier_diff, later_diff=later_diff)
362-
combined_nodes = self._combine_nodes(node_pairs=filtered_node_pairs)
363-
self._link_child_nodes(nodes=combined_nodes)
364-
return EnrichedDiffRoot(
365-
uuid=str(uuid4()),
366-
base_branch_name=later_diff.base_branch_name,
367-
diff_branch_name=later_diff.diff_branch_name,
368-
from_time=earlier_diff.from_time,
369-
to_time=later_diff.to_time,
370-
nodes=combined_nodes,
360+
async def combine(self, earlier_diffs: EnrichedDiffs, later_diffs: EnrichedDiffs) -> EnrichedDiffs:
361+
combined_diffs: list[EnrichedDiffRoot] = []
362+
for earlier, later in (
363+
(earlier_diffs.base_branch_diff, later_diffs.base_branch_diff),
364+
(earlier_diffs.diff_branch_diff, later_diffs.diff_branch_diff),
365+
):
366+
self._initialize(earlier_diff=earlier, later_diff=later)
367+
filtered_node_pairs = self._filter_nodes_to_keep(earlier_diff=earlier, later_diff=later)
368+
combined_nodes = self._combine_nodes(node_pairs=filtered_node_pairs)
369+
self._link_child_nodes(nodes=combined_nodes)
370+
combined_diffs.append(
371+
EnrichedDiffRoot(
372+
uuid=str(uuid4()),
373+
partner_uuid=later.partner_uuid,
374+
base_branch_name=later.base_branch_name,
375+
diff_branch_name=later.diff_branch_name,
376+
from_time=earlier.from_time,
377+
to_time=later.to_time,
378+
nodes=combined_nodes,
379+
)
380+
)
381+
base_branch_diff, diff_branch_diff = combined_diffs # pylint: disable=unbalanced-tuple-unpacking
382+
base_branch_diff.partner_uuid = diff_branch_diff.uuid
383+
diff_branch_diff.partner_uuid = base_branch_diff.uuid
384+
return EnrichedDiffs(
385+
base_branch_name=later_diffs.base_branch_name,
386+
diff_branch_name=later_diffs.diff_branch_name,
387+
base_branch_diff=base_branch_diff,
388+
diff_branch_diff=diff_branch_diff,
371389
)

backend/infrahub/core/diff/conflicts_enricher.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from infrahub.core.constants import DiffAction, RelationshipCardinality
44
from infrahub.core.constants.database import DatabaseEdgeType
5-
from infrahub.database import InfrahubDatabase
65

76
from .model.path import (
87
EnrichedDiffAttribute,
@@ -16,10 +15,9 @@
1615

1716

1817
class ConflictsEnricher:
19-
def __init__(self, db: InfrahubDatabase) -> None:
18+
def __init__(self) -> None:
2019
self._base_branch_name: str | None = None
2120
self._diff_branch_name: str | None = None
22-
self.schema_manager = db.schema
2321

2422
@property
2523
def base_branch_name(self) -> str:
@@ -66,7 +64,6 @@ def _add_node_conflicts(self, base_node: EnrichedDiffNode, branch_node: Enriched
6664
base_relationship = base_relationship_map[relationship_name]
6765
branch_relationship = branch_relationship_map[relationship_name]
6866
self._add_relationship_conflicts(
69-
branch_node=branch_node,
7067
base_relationship=base_relationship,
7168
branch_relationship=branch_relationship,
7269
)
@@ -100,7 +97,11 @@ def _add_attribute_conflicts(
10097
for property_type in common_property_types:
10198
base_property = base_property_map[property_type]
10299
branch_property = branch_property_map[property_type]
103-
if base_property.new_value != branch_property.new_value:
100+
same_value = base_property.new_value == branch_property.new_value or (
101+
base_property.action is DiffAction.UNCHANGED
102+
and base_property.previous_value == branch_property.previous_value
103+
)
104+
if not same_value:
104105
self._add_property_conflict(
105106
base_property=base_property,
106107
branch_property=branch_property,
@@ -110,15 +111,10 @@ def _add_attribute_conflicts(
110111

111112
def _add_relationship_conflicts(
112113
self,
113-
branch_node: EnrichedDiffNode,
114114
base_relationship: EnrichedDiffRelationship,
115115
branch_relationship: EnrichedDiffRelationship,
116116
) -> None:
117-
node_schema = self.schema_manager.get_node_schema(
118-
name=branch_node.kind, branch=self.diff_branch_name, duplicate=False
119-
)
120-
relationship_schema = node_schema.get_relationship(name=branch_relationship.name)
121-
is_cardinality_one = relationship_schema.cardinality is RelationshipCardinality.ONE
117+
is_cardinality_one = branch_relationship.cardinality is RelationshipCardinality.ONE
122118
if is_cardinality_one:
123119
if not base_relationship.relationships or not branch_relationship.relationships:
124120
return

0 commit comments

Comments
 (0)