infrahub-server 1.1.7__py3-none-any.whl → 1.1.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. infrahub/config.py +6 -0
  2. infrahub/core/diff/enricher/cardinality_one.py +5 -0
  3. infrahub/core/diff/enricher/hierarchy.py +17 -4
  4. infrahub/core/diff/enricher/labels.py +5 -0
  5. infrahub/core/diff/enricher/path_identifier.py +5 -0
  6. infrahub/core/diff/model/path.py +24 -1
  7. infrahub/core/diff/parent_node_adder.py +78 -0
  8. infrahub/core/diff/payload_builder.py +13 -2
  9. infrahub/core/diff/query/merge.py +20 -17
  10. infrahub/core/diff/query/save.py +188 -182
  11. infrahub/core/diff/query/summary_counts_enricher.py +51 -4
  12. infrahub/core/diff/repository/deserializer.py +8 -3
  13. infrahub/core/diff/repository/repository.py +156 -38
  14. infrahub/core/diff/tasks.py +4 -4
  15. infrahub/core/graph/__init__.py +1 -1
  16. infrahub/core/graph/index.py +3 -0
  17. infrahub/core/migrations/graph/__init__.py +6 -0
  18. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
  19. infrahub/core/migrations/graph/m020_duplicate_edges.py +160 -0
  20. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +51 -0
  21. infrahub/core/migrations/query/node_duplicate.py +38 -18
  22. infrahub/core/migrations/schema/node_remove.py +26 -12
  23. infrahub/core/migrations/shared.py +10 -8
  24. infrahub/core/node/__init__.py +13 -8
  25. infrahub/core/node/constraints/grouped_uniqueness.py +16 -3
  26. infrahub/core/query/attribute.py +2 -0
  27. infrahub/core/query/node.py +69 -19
  28. infrahub/core/query/relationship.py +105 -16
  29. infrahub/core/query/resource_manager.py +2 -0
  30. infrahub/core/relationship/model.py +8 -12
  31. infrahub/core/schema/definitions/core.py +1 -0
  32. infrahub/database/__init__.py +10 -1
  33. infrahub/database/metrics.py +7 -1
  34. infrahub/dependencies/builder/diff/deserializer.py +3 -1
  35. infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
  36. infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
  37. infrahub/graphql/initialization.py +3 -0
  38. infrahub/graphql/loaders/node.py +2 -12
  39. infrahub/graphql/loaders/peers.py +77 -0
  40. infrahub/graphql/loaders/shared.py +13 -0
  41. infrahub/graphql/mutations/diff.py +17 -10
  42. infrahub/graphql/mutations/resource_manager.py +3 -3
  43. infrahub/graphql/resolvers/many_relationship.py +264 -0
  44. infrahub/graphql/resolvers/resolver.py +3 -103
  45. infrahub/graphql/subscription/graphql_query.py +2 -0
  46. infrahub_sdk/batch.py +2 -2
  47. infrahub_sdk/client.py +10 -2
  48. infrahub_sdk/config.py +4 -1
  49. infrahub_sdk/ctl/check.py +4 -4
  50. infrahub_sdk/ctl/cli_commands.py +16 -11
  51. infrahub_sdk/ctl/exceptions.py +0 -6
  52. infrahub_sdk/ctl/exporter.py +1 -1
  53. infrahub_sdk/ctl/generator.py +5 -5
  54. infrahub_sdk/ctl/importer.py +3 -2
  55. infrahub_sdk/ctl/menu.py +1 -1
  56. infrahub_sdk/ctl/object.py +1 -1
  57. infrahub_sdk/ctl/repository.py +23 -15
  58. infrahub_sdk/ctl/schema.py +2 -2
  59. infrahub_sdk/ctl/utils.py +6 -5
  60. infrahub_sdk/ctl/validate.py +2 -1
  61. infrahub_sdk/data.py +1 -1
  62. infrahub_sdk/exceptions.py +12 -0
  63. infrahub_sdk/generator.py +3 -0
  64. infrahub_sdk/node.py +8 -8
  65. infrahub_sdk/protocols.py +0 -1
  66. infrahub_sdk/schema/__init__.py +0 -3
  67. infrahub_sdk/testing/docker.py +30 -0
  68. infrahub_sdk/testing/schemas/animal.py +9 -0
  69. infrahub_sdk/transfer/exporter/json.py +1 -1
  70. infrahub_sdk/utils.py +11 -1
  71. infrahub_sdk/yaml.py +2 -3
  72. {infrahub_server-1.1.7.dist-info → infrahub_server-1.1.9.dist-info}/METADATA +1 -1
  73. {infrahub_server-1.1.7.dist-info → infrahub_server-1.1.9.dist-info}/RECORD +78 -71
  74. infrahub_testcontainers/container.py +11 -0
  75. infrahub_testcontainers/docker-compose.test.yml +3 -6
  76. infrahub_sdk/ctl/_file.py +0 -13
  77. {infrahub_server-1.1.7.dist-info → infrahub_server-1.1.9.dist-info}/LICENSE.txt +0 -0
  78. {infrahub_server-1.1.7.dist-info → infrahub_server-1.1.9.dist-info}/WHEEL +0 -0
  79. {infrahub_server-1.1.7.dist-info → infrahub_server-1.1.9.dist-info}/entry_points.txt +0 -0
infrahub/config.py CHANGED
@@ -249,6 +249,12 @@ class DatabaseSettings(BaseSettings):
249
249
  retry_limit: int = Field(
250
250
  default=3, description="Maximum number of times a transient issue in a transaction should be retried."
251
251
  )
252
+ max_concurrent_queries: int = Field(
253
+ default=0, ge=0, description="Maximum number of concurrent queries that can run (0 means unlimited)."
254
+ )
255
+ max_concurrent_queries_delay: float = Field(
256
+ default=0.01, ge=0, description="Delay to add when max_concurrent_queries is reached."
257
+ )
252
258
 
253
259
  @property
254
260
  def database_name(self) -> str:
@@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Any
3
3
  from infrahub.core.constants import NULL_VALUE, DiffAction, RelationshipCardinality
4
4
  from infrahub.core.constants.database import DatabaseEdgeType
5
5
  from infrahub.database import InfrahubDatabase
6
+ from infrahub.log import get_logger
6
7
 
7
8
  from ..model.path import (
8
9
  CalculatedDiffs,
@@ -16,6 +17,8 @@ from .interface import DiffEnricherInterface
16
17
  if TYPE_CHECKING:
17
18
  from infrahub.core.schema import MainSchemaTypes
18
19
 
20
+ log = get_logger()
21
+
19
22
 
20
23
  class DiffCardinalityOneEnricher(DiffEnricherInterface):
21
24
  """Clean up diffs for cardinality=one relationships to make them cleaner and more intuitive
@@ -34,6 +37,7 @@ class DiffCardinalityOneEnricher(DiffEnricherInterface):
34
37
 
35
38
  async def enrich(self, enriched_diff_root: EnrichedDiffRoot, calculated_diffs: CalculatedDiffs) -> None:
36
39
  self._node_schema_map = {}
40
+ log.info("Beginning cardinality-one diff enrichment...")
37
41
  for diff_node in enriched_diff_root.nodes:
38
42
  for relationship_group in diff_node.relationships:
39
43
  if (
@@ -41,6 +45,7 @@ class DiffCardinalityOneEnricher(DiffEnricherInterface):
41
45
  and len(relationship_group.relationships) > 0
42
46
  ):
43
47
  self.consolidate_cardinality_one_diff_elements(diff_relationship=relationship_group)
48
+ log.info("Cardinality-one diff enrichment complete.")
44
49
 
45
50
  def _determine_action(self, previous_value: Any, new_value: Any) -> DiffAction:
46
51
  if previous_value == new_value:
@@ -7,19 +7,24 @@ from infrahub.core.query.node import NodeGetHierarchyQuery
7
7
  from infrahub.core.query.relationship import RelationshipGetPeerQuery, RelationshipPeerData
8
8
  from infrahub.core.schema import ProfileSchema
9
9
  from infrahub.database import InfrahubDatabase
10
+ from infrahub.log import get_logger
10
11
 
11
12
  from ..model.path import (
12
13
  CalculatedDiffs,
13
14
  EnrichedDiffRoot,
14
15
  )
16
+ from ..parent_node_adder import DiffParentNodeAdder, ParentNodeAddRequest
15
17
  from .interface import DiffEnricherInterface
16
18
 
19
+ log = get_logger()
20
+
17
21
 
18
22
  class DiffHierarchyEnricher(DiffEnricherInterface):
19
23
  """Add hierarchy and parent/component nodes to diff even if the higher-level nodes are unchanged"""
20
24
 
21
- def __init__(self, db: InfrahubDatabase):
25
+ def __init__(self, db: InfrahubDatabase, parent_adder: DiffParentNodeAdder):
22
26
  self.db = db
27
+ self.parent_adder = parent_adder
23
28
 
24
29
  async def enrich(
25
30
  self, enriched_diff_root: EnrichedDiffRoot, calculated_diffs: CalculatedDiffs | None = None
@@ -28,6 +33,8 @@ class DiffHierarchyEnricher(DiffEnricherInterface):
28
33
  # - A node has a relationship of kind parent
29
34
  # - A node is part of a hierarchy
30
35
 
36
+ log.info("Beginning hierarchical diff enrichment...")
37
+ self.parent_adder.initialize(enriched_diff_root=enriched_diff_root)
31
38
  node_rel_parent_map: dict[str, list[str]] = defaultdict(list)
32
39
  node_hierarchy_map: dict[str, list[str]] = defaultdict(list)
33
40
 
@@ -53,6 +60,7 @@ class DiffHierarchyEnricher(DiffEnricherInterface):
53
60
 
54
61
  await self._enrich_nodes_with_parent(enriched_diff_root=enriched_diff_root, node_map=node_rel_parent_map)
55
62
  await self._enrich_hierarchical_nodes(enriched_diff_root=enriched_diff_root, node_map=node_hierarchy_map)
63
+ log.info("Hierarchical diff enrichment complete.")
56
64
 
57
65
  async def _enrich_hierarchical_nodes(
58
66
  self,
@@ -63,6 +71,7 @@ class DiffHierarchyEnricher(DiffEnricherInterface):
63
71
 
64
72
  # Retrieve the ID of all ancestors
65
73
  for kind, node_ids in node_map.items():
74
+ log.info(f"Beginning hierarchy enrichment for {kind} node, num_nodes={len(node_ids)}...")
66
75
  hierarchy_schema = self.db.schema.get(
67
76
  name=kind, branch=enriched_diff_root.diff_branch_name, duplicate=False
68
77
  )
@@ -87,7 +96,7 @@ class DiffHierarchyEnricher(DiffEnricherInterface):
87
96
 
88
97
  current_node = node
89
98
  for ancestor in ancestors:
90
- parent = enriched_diff_root.add_parent(
99
+ parent_request = ParentNodeAddRequest(
91
100
  node_id=current_node.uuid,
92
101
  parent_id=str(ancestor.uuid),
93
102
  parent_kind=ancestor.kind,
@@ -97,6 +106,7 @@ class DiffHierarchyEnricher(DiffEnricherInterface):
97
106
  parent_rel_cardinality=parent_rel.cardinality,
98
107
  parent_rel_label=parent_rel.label or "",
99
108
  )
109
+ parent = self.parent_adder.add_parent(parent_request=parent_request)
100
110
 
101
111
  current_node = parent
102
112
 
@@ -114,6 +124,7 @@ class DiffHierarchyEnricher(DiffEnricherInterface):
114
124
 
115
125
  # Query the UUID of the parent
116
126
  for kind, ids in node_map.items():
127
+ log.info(f"Beginning parent enrichment for {kind} node, num_nodes={len(ids)}...")
117
128
  schema_node = self.db.schema.get(name=kind, branch=enriched_diff_root.diff_branch_name, duplicate=False)
118
129
 
119
130
  parent_rel = [rel for rel in schema_node.relationships if rel.kind == RelationshipKind.PARENT][0]
@@ -138,15 +149,16 @@ class DiffHierarchyEnricher(DiffEnricherInterface):
138
149
  # Check if the parent are already present
139
150
  # If parent is already in the list of node we need to add a relationship
140
151
  # If parent is not in the list of node, we need to add it
152
+ diff_node_map = enriched_diff_root.get_node_map(node_uuids=set(parent_peers.keys()))
141
153
  for node_id, peer_parent in parent_peers.items():
142
154
  # TODO check if we can optimize this part to avoid querying this multiple times
143
- node = enriched_diff_root.get_node(node_uuid=node_id)
155
+ node = diff_node_map[node_id]
144
156
  schema_node = self.db.schema.get(
145
157
  name=node.kind, branch=enriched_diff_root.diff_branch_name, duplicate=False
146
158
  )
147
159
  parent_rel = [rel for rel in schema_node.relationships if rel.kind == RelationshipKind.PARENT][0]
148
160
 
149
- enriched_diff_root.add_parent(
161
+ parent_request = ParentNodeAddRequest(
150
162
  node_id=node.uuid,
151
163
  parent_id=str(peer_parent.peer_id),
152
164
  parent_kind=peer_parent.peer_kind,
@@ -156,6 +168,7 @@ class DiffHierarchyEnricher(DiffEnricherInterface):
156
168
  parent_rel_cardinality=parent_rel.cardinality,
157
169
  parent_rel_label=parent_rel.label or "",
158
170
  )
171
+ self.parent_adder.add_parent(parent_request=parent_request)
159
172
 
160
173
  if node_parent_with_parent_map:
161
174
  await self._enrich_nodes_with_parent(
@@ -6,6 +6,7 @@ from infrahub.core.constants import DiffAction
6
6
  from infrahub.core.constants.database import DatabaseEdgeType
7
7
  from infrahub.core.query.node import NodeGetKindQuery
8
8
  from infrahub.database import InfrahubDatabase
9
+ from infrahub.log import get_logger
9
10
 
10
11
  from ..model.path import (
11
12
  CalculatedDiffs,
@@ -17,6 +18,8 @@ from ..model.path import (
17
18
  from ..payload_builder import get_display_labels
18
19
  from .interface import DiffEnricherInterface
19
20
 
21
+ log = get_logger()
22
+
20
23
  PROPERTY_TYPES_WITH_LABELS = {DatabaseEdgeType.IS_RELATED, DatabaseEdgeType.HAS_OWNER, DatabaseEdgeType.HAS_SOURCE}
21
24
 
22
25
 
@@ -194,6 +197,7 @@ class DiffLabelsEnricher(DiffEnricherInterface):
194
197
  calculated_diffs: CalculatedDiffs | None = None,
195
198
  conflicts_only: bool = False,
196
199
  ) -> None:
200
+ log.info("Beginning display labels diff enrichment...")
197
201
  self._base_branch_name = enriched_diff_root.base_branch_name
198
202
  self._diff_branch_name = enriched_diff_root.diff_branch_name
199
203
  self._conflicts_only = conflicts_only
@@ -214,3 +218,4 @@ class DiffLabelsEnricher(DiffEnricherInterface):
214
218
  ...
215
219
 
216
220
  self._update_relationship_labels(enriched_diff=enriched_diff_root)
221
+ log.info("Display labels diff enrichment complete.")
@@ -1,10 +1,13 @@
1
1
  from infrahub.core.constants import PathType
2
2
  from infrahub.core.path import DataPath
3
3
  from infrahub.database import InfrahubDatabase
4
+ from infrahub.log import get_logger
4
5
 
5
6
  from ..model.path import CalculatedDiffs, EnrichedDiffRoot
6
7
  from .interface import DiffEnricherInterface
7
8
 
9
+ log = get_logger()
10
+
8
11
 
9
12
  class DiffPathIdentifierEnricher(DiffEnricherInterface):
10
13
  """Add path identifiers to every element in the diff"""
@@ -20,6 +23,7 @@ class DiffPathIdentifierEnricher(DiffEnricherInterface):
20
23
  return self._diff_branch_name
21
24
 
22
25
  async def enrich(self, enriched_diff_root: EnrichedDiffRoot, calculated_diffs: CalculatedDiffs) -> None:
26
+ log.info("Beginning path identifier diff enrichment...")
23
27
  self._diff_branch_name = enriched_diff_root.diff_branch_name
24
28
  for node in enriched_diff_root.nodes:
25
29
  node_path = DataPath(
@@ -62,3 +66,4 @@ class DiffPathIdentifierEnricher(DiffEnricherInterface):
62
66
  relationship_property_path = relationship_element_path.model_copy()
63
67
  relationship_property_path.property_name = relationship_property.property_type.value
64
68
  relationship_property.path_identifier = relationship_property_path.get_path(with_peer=False)
69
+ log.info("Path identifier diff enrichment complete.")
@@ -163,6 +163,10 @@ class EnrichedDiffAttribute(BaseSummary):
163
163
  def __hash__(self) -> int:
164
164
  return hash(self.name)
165
165
 
166
+ @property
167
+ def num_properties(self) -> int:
168
+ return len(self.properties)
169
+
166
170
  def get_all_conflicts(self) -> dict[str, EnrichedDiffConflict]:
167
171
  return {prop.path_identifier: prop.conflict for prop in self.properties if prop.conflict}
168
172
 
@@ -202,6 +206,10 @@ class EnrichedDiffSingleRelationship(BaseSummary):
202
206
  def __hash__(self) -> int:
203
207
  return hash(self.peer_id)
204
208
 
209
+ @property
210
+ def num_properties(self) -> int:
211
+ return len(self.properties)
212
+
205
213
  def get_all_conflicts(self) -> dict[str, EnrichedDiffConflict]:
206
214
  all_conflicts: dict[str, EnrichedDiffConflict] = {}
207
215
  if self.conflict:
@@ -248,6 +256,10 @@ class EnrichedDiffRelationship(BaseSummary):
248
256
  def __hash__(self) -> int:
249
257
  return hash(self.name)
250
258
 
259
+ @property
260
+ def num_properties(self) -> int:
261
+ return sum(r.num_properties for r in self.relationships)
262
+
251
263
  def get_all_conflicts(self) -> dict[str, EnrichedDiffConflict]:
252
264
  all_conflicts: dict[str, EnrichedDiffConflict] = {}
253
265
  for element in self.relationships:
@@ -308,6 +320,10 @@ class EnrichedDiffNode(BaseSummary):
308
320
  def __hash__(self) -> int:
309
321
  return hash(self.uuid)
310
322
 
323
+ @property
324
+ def num_properties(self) -> int:
325
+ return sum(a.num_properties for a in self.attributes) + sum(r.num_properties for r in self.relationships)
326
+
311
327
  def get_all_conflicts(self) -> dict[str, EnrichedDiffConflict]:
312
328
  all_conflicts: dict[str, EnrichedDiffConflict] = {}
313
329
  if self.conflict:
@@ -409,8 +425,8 @@ class EnrichedDiffRootMetadata(BaseSummary):
409
425
  from_time: Timestamp
410
426
  to_time: Timestamp
411
427
  uuid: str
412
- partner_uuid: str
413
428
  tracking_id: TrackingId
429
+ partner_uuid: str | None = field(default=None)
414
430
  exists_on_database: bool = field(default=False)
415
431
 
416
432
  def __hash__(self) -> int:
@@ -470,6 +486,13 @@ class EnrichedDiffRoot(EnrichedDiffRootMetadata):
470
486
  except ValueError:
471
487
  return False
472
488
 
489
+ def get_node_map(self, node_uuids: set[str] | None = None) -> dict[str, EnrichedDiffNode]:
490
+ node_map = {}
491
+ for node in self.nodes:
492
+ if node_uuids is None or node.uuid in node_uuids:
493
+ node_map[node.uuid] = node
494
+ return node_map
495
+
473
496
  def get_all_conflicts(self) -> dict[str, EnrichedDiffConflict]:
474
497
  all_conflicts: dict[str, EnrichedDiffConflict] = {}
475
498
  for node in self.nodes:
@@ -0,0 +1,78 @@
1
+ from dataclasses import dataclass, field
2
+
3
+ from infrahub.core.constants import DiffAction, RelationshipCardinality
4
+
5
+ from .model.path import EnrichedDiffNode, EnrichedDiffRelationship, EnrichedDiffRoot
6
+
7
+
8
+ @dataclass
9
+ class ParentNodeAddRequest:
10
+ node_id: str
11
+ parent_id: str
12
+ parent_kind: str
13
+ parent_label: str
14
+ parent_rel_name: str
15
+ parent_rel_identifier: str
16
+ parent_rel_cardinality: RelationshipCardinality
17
+ parent_rel_label: str = field(default="")
18
+
19
+
20
+ class DiffParentNodeAdder:
21
+ def __init__(self) -> None:
22
+ self._diff_root: EnrichedDiffRoot | None = None
23
+ self._node_map: dict[str, EnrichedDiffNode] = {}
24
+
25
+ def initialize(self, enriched_diff_root: EnrichedDiffRoot) -> None:
26
+ self._diff_root = enriched_diff_root
27
+ self._node_map = enriched_diff_root.get_node_map()
28
+
29
+ def get_root(self) -> EnrichedDiffRoot:
30
+ if not self._diff_root:
31
+ raise RuntimeError("Must call initialize before using")
32
+ return self._diff_root
33
+
34
+ def get_node(self, node_uuid: str) -> EnrichedDiffNode:
35
+ return self._node_map[node_uuid]
36
+
37
+ def has_node(self, node_uuid: str) -> bool:
38
+ return node_uuid in self._node_map
39
+
40
+ def add_node(self, node: EnrichedDiffNode) -> None:
41
+ if node.uuid in self._node_map:
42
+ return
43
+ self._node_map[node.uuid] = node
44
+ self.get_root().nodes.add(node)
45
+
46
+ def add_parent(self, parent_request: ParentNodeAddRequest) -> EnrichedDiffNode:
47
+ if not self._diff_root:
48
+ raise RuntimeError("Must call initialize before using")
49
+ node = self.get_node(node_uuid=parent_request.node_id)
50
+ if not self.has_node(node_uuid=parent_request.parent_id):
51
+ parent = EnrichedDiffNode(
52
+ uuid=parent_request.parent_id,
53
+ kind=parent_request.parent_kind,
54
+ label=parent_request.parent_label,
55
+ action=DiffAction.UNCHANGED,
56
+ changed_at=None,
57
+ )
58
+ self.add_node(parent)
59
+ else:
60
+ parent = self.get_node(node_uuid=parent_request.parent_id)
61
+
62
+ try:
63
+ rel = node.get_relationship(name=parent_request.parent_rel_name)
64
+ rel.nodes.add(parent)
65
+ except ValueError:
66
+ node.relationships.add(
67
+ EnrichedDiffRelationship(
68
+ name=parent_request.parent_rel_name,
69
+ identifier=parent_request.parent_rel_identifier,
70
+ label=parent_request.parent_rel_label,
71
+ cardinality=parent_request.parent_rel_cardinality,
72
+ changed_at=None,
73
+ action=DiffAction.UNCHANGED,
74
+ nodes={parent},
75
+ )
76
+ )
77
+
78
+ return parent
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING
4
4
 
5
+ from infrahub import config
5
6
  from infrahub.core.manager import NodeManager
6
7
  from infrahub.core.registry import registry
7
8
  from infrahub.exceptions import SchemaNotFoundError
@@ -26,8 +27,18 @@ async def get_display_labels_per_kind(
26
27
  if skip_missing_schema:
27
28
  return {}
28
29
  raise
29
- nodes = await NodeManager.get_many(ids=ids, fields=fields, db=db, branch=branch)
30
- return {node_id: await node.render_display_label(db=db) for node_id, node in nodes.items()}
30
+ display_label_map: dict[str, str] = {}
31
+ offset = 0
32
+ limit = config.SETTINGS.database.query_size_limit
33
+ while True:
34
+ limited_ids = ids[offset : offset + limit]
35
+ if not limited_ids:
36
+ break
37
+ node_map = await NodeManager.get_many(ids=limited_ids, fields=fields, db=db, branch=branch)
38
+ for node_id, node in node_map.items():
39
+ display_label_map[node_id] = await node.render_display_label(db=db)
40
+ offset += limit
41
+ return display_label_map
31
42
 
32
43
 
33
44
  async def get_display_labels(nodes: dict[str, dict[str, list[str]]], db: InfrahubDatabase) -> dict[str, dict[str, str]]:
@@ -36,6 +36,7 @@ class DiffMergeQuery(Query):
36
36
  "target_branch": self.target_branch.name,
37
37
  "source_branch": self.source_branch_name,
38
38
  }
39
+ # ruff: noqa: E501
39
40
  query = """
40
41
  UNWIND $node_diff_dicts AS node_diff_map
41
42
  CALL {
@@ -242,9 +243,11 @@ CALL {
242
243
  CASE
243
244
  WHEN startNode(source_r_rel_2).uuid = r.uuid THEN "r"
244
245
  ELSE "l"
245
- END AS r2_dir
246
+ END AS r2_dir,
247
+ source_r_rel_1.hierarchy AS r1_hierarchy,
248
+ source_r_rel_2.hierarchy AS r2_hierarchy
246
249
  }
247
- WITH n, r, r1_dir, r2_dir, rel_name, rel_peer_id, related_rel_status
250
+ WITH n, r, r1_dir, r2_dir, r1_hierarchy, r2_hierarchy, rel_name, rel_peer_id, related_rel_status
248
251
  CALL {
249
252
  WITH n, rel_name, rel_peer_id, related_rel_status
250
253
  OPTIONAL MATCH (n)
@@ -258,12 +261,12 @@ CALL {
258
261
  SET target_r_rel_1.to = $at
259
262
  SET target_r_rel_2.to = $at
260
263
  }
261
- WITH n, r, r1_dir, r2_dir, rel_name, rel_peer_id, related_rel_status
264
+ WITH n, r, r1_dir, r2_dir, r1_hierarchy, r2_hierarchy, rel_name, rel_peer_id, related_rel_status
262
265
  // ------------------------------
263
266
  // conditionally create new IS_RELATED relationships on target_branch, if necessary
264
267
  // ------------------------------
265
268
  CALL {
266
- WITH n, r, r1_dir, r2_dir, rel_name, rel_peer_id, related_rel_status
269
+ WITH n, r, r1_dir, r2_dir, r1_hierarchy, r2_hierarchy, rel_name, rel_peer_id, related_rel_status
267
270
  MATCH (p:Node {uuid: rel_peer_id})
268
271
  OPTIONAL MATCH (n)
269
272
  -[r_rel_1:IS_RELATED {branch: $target_branch, status: related_rel_status}]
@@ -274,42 +277,42 @@ CALL {
274
277
  AND (r_rel_1.to >= $at OR r_rel_1.to IS NULL)
275
278
  AND r_rel_2.from <= $at
276
279
  AND (r_rel_2.to >= $at OR r_rel_2.to IS NULL)
277
- WITH n, r, r1_dir, r2_dir, p, related_rel_status, r_rel_1, r_rel_2
280
+ WITH n, r, r1_dir, r2_dir, r1_hierarchy, r2_hierarchy, p, related_rel_status, r_rel_1, r_rel_2
278
281
  WHERE r_rel_1 IS NULL
279
282
  AND r_rel_2 IS NULL
280
283
  // ------------------------------
281
284
  // create IS_RELATED relationships with directions maintained from source
282
285
  // ------------------------------
283
286
  CALL {
284
- WITH n, r, r1_dir, related_rel_status
285
- WITH n, r, r1_dir, related_rel_status
287
+ WITH n, r, r1_dir, r1_hierarchy, related_rel_status
288
+ WITH n, r, r1_dir, r1_hierarchy, related_rel_status
286
289
  WHERE r1_dir = "r"
287
290
  CREATE (n)
288
- -[:IS_RELATED {branch: $target_branch, branch_level: $branch_level, from: $at, status: related_rel_status}]
291
+ -[:IS_RELATED {branch: $target_branch, branch_level: $branch_level, from: $at, status: related_rel_status, hierarchy: r1_hierarchy}]
289
292
  ->(r)
290
293
  }
291
294
  CALL {
292
- WITH n, r, r1_dir, related_rel_status
293
- WITH n, r, r1_dir, related_rel_status
295
+ WITH n, r, r1_dir, r1_hierarchy, related_rel_status
296
+ WITH n, r, r1_dir, r1_hierarchy, related_rel_status
294
297
  WHERE r1_dir = "l"
295
298
  CREATE (n)
296
- <-[:IS_RELATED {branch: $target_branch, branch_level: $branch_level, from: $at, status: related_rel_status}]
299
+ <-[:IS_RELATED {branch: $target_branch, branch_level: $branch_level, from: $at, status: related_rel_status, hierarchy: r1_hierarchy}]
297
300
  -(r)
298
301
  }
299
302
  CALL {
300
- WITH r, p, r2_dir, related_rel_status
301
- WITH r, p, r2_dir, related_rel_status
303
+ WITH r, p, r2_dir, r2_hierarchy, related_rel_status
304
+ WITH r, p, r2_dir, r2_hierarchy, related_rel_status
302
305
  WHERE r2_dir = "r"
303
306
  CREATE (r)
304
- -[:IS_RELATED {branch: $target_branch, branch_level: $branch_level, from: $at, status: related_rel_status}]
307
+ -[:IS_RELATED {branch: $target_branch, branch_level: $branch_level, from: $at, status: related_rel_status, hierarchy: r2_hierarchy}]
305
308
  ->(p)
306
309
  }
307
310
  CALL {
308
- WITH r, p, r2_dir, related_rel_status
309
- WITH r, p, r2_dir, related_rel_status
311
+ WITH r, p, r2_dir, r2_hierarchy, related_rel_status
312
+ WITH r, p, r2_dir, r2_hierarchy, related_rel_status
310
313
  WHERE r2_dir = "l"
311
314
  CREATE (r)
312
- <-[:IS_RELATED {branch: $target_branch, branch_level: $branch_level, from: $at, status: related_rel_status}]
315
+ <-[:IS_RELATED {branch: $target_branch, branch_level: $branch_level, from: $at, status: related_rel_status, hierarchy: r2_hierarchy}]
313
316
  -(p)
314
317
  }
315
318
  }