infrahub-server 1.1.6__py3-none-any.whl → 1.1.8__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.
- infrahub/core/attribute.py +4 -1
- infrahub/core/branch/tasks.py +7 -4
- infrahub/core/diff/combiner.py +11 -7
- infrahub/core/diff/coordinator.py +49 -70
- infrahub/core/diff/data_check_synchronizer.py +86 -7
- infrahub/core/diff/enricher/aggregated.py +3 -3
- infrahub/core/diff/enricher/cardinality_one.py +6 -6
- infrahub/core/diff/enricher/hierarchy.py +17 -4
- infrahub/core/diff/enricher/labels.py +18 -3
- infrahub/core/diff/enricher/path_identifier.py +7 -8
- infrahub/core/diff/merger/merger.py +5 -3
- infrahub/core/diff/model/path.py +66 -25
- infrahub/core/diff/parent_node_adder.py +78 -0
- infrahub/core/diff/payload_builder.py +13 -2
- infrahub/core/diff/query/all_conflicts.py +5 -2
- infrahub/core/diff/query/diff_get.py +2 -1
- infrahub/core/diff/query/field_specifiers.py +2 -0
- infrahub/core/diff/query/field_summary.py +2 -1
- infrahub/core/diff/query/filters.py +12 -1
- infrahub/core/diff/query/has_conflicts_query.py +5 -2
- infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +3 -3
- infrahub/core/diff/query/roots_metadata.py +8 -1
- infrahub/core/diff/query/save.py +230 -139
- infrahub/core/diff/query/summary_counts_enricher.py +267 -0
- infrahub/core/diff/query/time_range_query.py +2 -1
- infrahub/core/diff/query_parser.py +49 -24
- infrahub/core/diff/repository/deserializer.py +31 -27
- infrahub/core/diff/repository/repository.py +215 -41
- infrahub/core/diff/tasks.py +4 -4
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/graph/index.py +3 -0
- infrahub/core/migrations/graph/__init__.py +4 -0
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
- infrahub/core/migrations/graph/m020_duplicate_edges.py +160 -0
- infrahub/core/migrations/query/node_duplicate.py +38 -18
- infrahub/core/migrations/schema/node_remove.py +26 -12
- infrahub/core/migrations/shared.py +10 -8
- infrahub/core/node/__init__.py +19 -9
- infrahub/core/node/constraints/grouped_uniqueness.py +25 -5
- infrahub/core/node/ipam.py +6 -1
- infrahub/core/node/permissions.py +4 -0
- infrahub/core/query/attribute.py +2 -0
- infrahub/core/query/diff.py +41 -3
- infrahub/core/query/node.py +74 -21
- infrahub/core/query/relationship.py +107 -17
- infrahub/core/query/resource_manager.py +5 -1
- infrahub/core/relationship/model.py +8 -12
- infrahub/core/schema/definitions/core.py +1 -0
- infrahub/core/utils.py +1 -0
- infrahub/core/validators/uniqueness/query.py +20 -17
- infrahub/database/__init__.py +14 -0
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
- infrahub/dependencies/builder/diff/coordinator.py +0 -2
- infrahub/dependencies/builder/diff/deserializer.py +3 -1
- infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
- infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
- infrahub/graphql/mutations/computed_attribute.py +3 -1
- infrahub/graphql/mutations/diff.py +41 -10
- infrahub/graphql/mutations/main.py +11 -6
- infrahub/graphql/mutations/relationship.py +29 -1
- infrahub/graphql/mutations/resource_manager.py +3 -3
- infrahub/graphql/mutations/tasks.py +6 -3
- infrahub/graphql/queries/resource_manager.py +7 -3
- infrahub/permissions/__init__.py +2 -1
- infrahub/permissions/types.py +26 -0
- infrahub_sdk/client.py +10 -2
- infrahub_sdk/config.py +3 -0
- infrahub_sdk/ctl/check.py +3 -3
- infrahub_sdk/ctl/cli_commands.py +16 -11
- infrahub_sdk/ctl/exceptions.py +0 -6
- infrahub_sdk/ctl/exporter.py +1 -1
- infrahub_sdk/ctl/generator.py +5 -5
- infrahub_sdk/ctl/importer.py +3 -2
- infrahub_sdk/ctl/menu.py +1 -1
- infrahub_sdk/ctl/object.py +1 -1
- infrahub_sdk/ctl/repository.py +23 -15
- infrahub_sdk/ctl/schema.py +2 -2
- infrahub_sdk/ctl/utils.py +4 -3
- infrahub_sdk/ctl/validate.py +2 -1
- infrahub_sdk/exceptions.py +12 -0
- infrahub_sdk/generator.py +3 -0
- infrahub_sdk/node.py +7 -4
- infrahub_sdk/testing/schemas/animal.py +9 -0
- infrahub_sdk/utils.py +11 -1
- infrahub_sdk/yaml.py +2 -3
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.8.dist-info}/METADATA +41 -7
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.8.dist-info}/RECORD +94 -91
- infrahub_testcontainers/container.py +12 -3
- infrahub_testcontainers/docker-compose.test.yml +22 -3
- infrahub_testcontainers/haproxy.cfg +43 -0
- infrahub_testcontainers/helpers.py +85 -1
- infrahub/core/diff/enricher/summary_counts.py +0 -105
- infrahub/dependencies/builder/diff/enricher/summary_counts.py +0 -8
- infrahub_sdk/ctl/_file.py +0 -13
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.8.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.8.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.8.dist-info}/entry_points.txt +0 -0
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
from collections import defaultdict
|
|
2
|
-
from typing import AsyncGenerator, Generator
|
|
2
|
+
from typing import AsyncGenerator, Generator, Iterable
|
|
3
|
+
|
|
4
|
+
from neo4j.exceptions import TransientError
|
|
3
5
|
|
|
4
6
|
from infrahub import config
|
|
5
7
|
from infrahub.core import registry
|
|
6
8
|
from infrahub.core.diff.query.field_summary import EnrichedDiffNodeFieldSummaryQuery
|
|
9
|
+
from infrahub.core.diff.query.summary_counts_enricher import (
|
|
10
|
+
DiffFieldsSummaryCountsEnricherQuery,
|
|
11
|
+
DiffNodesSummaryCountsEnricherQuery,
|
|
12
|
+
)
|
|
7
13
|
from infrahub.core.query.diff import DiffCountChanges
|
|
8
14
|
from infrahub.core.timestamp import Timestamp
|
|
9
15
|
from infrahub.database import InfrahubDatabase, retry_db_transaction
|
|
@@ -13,6 +19,7 @@ from infrahub.log import get_logger
|
|
|
13
19
|
from ..model.path import (
|
|
14
20
|
ConflictSelection,
|
|
15
21
|
EnrichedDiffConflict,
|
|
22
|
+
EnrichedDiffNode,
|
|
16
23
|
EnrichedDiffRoot,
|
|
17
24
|
EnrichedDiffRootMetadata,
|
|
18
25
|
EnrichedDiffs,
|
|
@@ -26,13 +33,13 @@ from ..query.all_conflicts import EnrichedDiffAllConflictsQuery
|
|
|
26
33
|
from ..query.delete_query import EnrichedDiffDeleteQuery
|
|
27
34
|
from ..query.diff_get import EnrichedDiffGetQuery
|
|
28
35
|
from ..query.diff_summary import DiffSummaryCounters, DiffSummaryQuery
|
|
29
|
-
from ..query.drop_tracking_id import EnrichedDiffDropTrackingIdQuery
|
|
30
36
|
from ..query.field_specifiers import EnrichedDiffFieldSpecifiersQuery
|
|
31
37
|
from ..query.filters import EnrichedDiffQueryFilters
|
|
32
38
|
from ..query.get_conflict_query import EnrichedDiffConflictQuery
|
|
33
39
|
from ..query.has_conflicts_query import EnrichedDiffHasConflictQuery
|
|
40
|
+
from ..query.merge_tracking_id import EnrichedDiffMergedTrackingIdQuery
|
|
34
41
|
from ..query.roots_metadata import EnrichedDiffRootsMetadataQuery
|
|
35
|
-
from ..query.save import
|
|
42
|
+
from ..query.save import EnrichedDiffRootsUpsertQuery, EnrichedNodeBatchCreateQuery, EnrichedNodesLinkQuery
|
|
36
43
|
from ..query.time_range_query import EnrichedDiffTimeRangeQuery
|
|
37
44
|
from ..query.update_conflict_query import EnrichedDiffConflictUpdateQuery
|
|
38
45
|
from .deserializer import EnrichedDiffDeserializer
|
|
@@ -41,17 +48,17 @@ log = get_logger()
|
|
|
41
48
|
|
|
42
49
|
|
|
43
50
|
class DiffRepository:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def __init__(self, db: InfrahubDatabase, deserializer: EnrichedDiffDeserializer):
|
|
51
|
+
def __init__(self, db: InfrahubDatabase, deserializer: EnrichedDiffDeserializer, max_save_batch_size: int = 1000):
|
|
47
52
|
self.db = db
|
|
48
53
|
self.deserializer = deserializer
|
|
54
|
+
self.max_save_batch_size = max_save_batch_size
|
|
49
55
|
|
|
50
56
|
async def _run_get_diff_query(
|
|
51
57
|
self,
|
|
52
58
|
base_branch_name: str,
|
|
53
59
|
diff_branch_names: list[str],
|
|
54
|
-
|
|
60
|
+
batch_size_limit: int,
|
|
61
|
+
limit: int | None = None,
|
|
55
62
|
from_time: Timestamp | None = None,
|
|
56
63
|
to_time: Timestamp | None = None,
|
|
57
64
|
filters: EnrichedDiffQueryFilters | None = None,
|
|
@@ -62,8 +69,13 @@ class DiffRepository:
|
|
|
62
69
|
diff_ids: list[str] | None = None,
|
|
63
70
|
) -> list[EnrichedDiffRoot]:
|
|
64
71
|
self.deserializer.initialize()
|
|
72
|
+
final_row_number = None
|
|
73
|
+
if limit:
|
|
74
|
+
final_row_number = offset + limit
|
|
65
75
|
has_more_data = True
|
|
66
|
-
while has_more_data:
|
|
76
|
+
while has_more_data and (final_row_number is None or offset < final_row_number):
|
|
77
|
+
if final_row_number is not None and offset + batch_size_limit > final_row_number:
|
|
78
|
+
batch_size_limit = final_row_number - offset
|
|
67
79
|
get_query = await EnrichedDiffGetQuery.init(
|
|
68
80
|
db=self.db,
|
|
69
81
|
base_branch_name=base_branch_name,
|
|
@@ -72,12 +84,12 @@ class DiffRepository:
|
|
|
72
84
|
to_time=to_time,
|
|
73
85
|
filters=filters,
|
|
74
86
|
max_depth=max_depth,
|
|
75
|
-
limit=
|
|
87
|
+
limit=batch_size_limit,
|
|
76
88
|
offset=offset,
|
|
77
89
|
tracking_id=tracking_id,
|
|
78
90
|
diff_ids=diff_ids,
|
|
79
91
|
)
|
|
80
|
-
log.info(f"Beginning enriched diff get query {
|
|
92
|
+
log.info(f"Beginning enriched diff get query {batch_size_limit=}, {offset=}")
|
|
81
93
|
await get_query.execute(db=self.db)
|
|
82
94
|
log.info("Enriched diff get query complete")
|
|
83
95
|
last_result = None
|
|
@@ -87,7 +99,7 @@ class DiffRepository:
|
|
|
87
99
|
has_more_data = False
|
|
88
100
|
if last_result:
|
|
89
101
|
has_more_data = last_result.get_as_type("has_more_data", bool)
|
|
90
|
-
offset +=
|
|
102
|
+
offset += batch_size_limit
|
|
91
103
|
return await self.deserializer.deserialize()
|
|
92
104
|
|
|
93
105
|
async def get(
|
|
@@ -105,16 +117,17 @@ class DiffRepository:
|
|
|
105
117
|
include_empty: bool = False,
|
|
106
118
|
) -> list[EnrichedDiffRoot]:
|
|
107
119
|
final_max_depth = config.SETTINGS.database.max_depth_search_hierarchy
|
|
108
|
-
|
|
120
|
+
batch_size_limit = int(config.SETTINGS.database.query_size_limit / 10)
|
|
109
121
|
diff_roots = await self._run_get_diff_query(
|
|
110
122
|
base_branch_name=base_branch_name,
|
|
111
123
|
diff_branch_names=diff_branch_names,
|
|
124
|
+
batch_size_limit=batch_size_limit,
|
|
125
|
+
limit=limit,
|
|
112
126
|
from_time=from_time,
|
|
113
127
|
to_time=to_time,
|
|
114
128
|
filters=EnrichedDiffQueryFilters(**dict(filters or {})),
|
|
115
129
|
include_parents=include_parents,
|
|
116
130
|
max_depth=final_max_depth,
|
|
117
|
-
limit=limit,
|
|
118
131
|
offset=offset or 0,
|
|
119
132
|
tracking_id=tracking_id,
|
|
120
133
|
diff_ids=diff_ids,
|
|
@@ -131,42 +144,56 @@ class DiffRepository:
|
|
|
131
144
|
to_time: Timestamp,
|
|
132
145
|
) -> list[EnrichedDiffs]:
|
|
133
146
|
max_depth = config.SETTINGS.database.max_depth_search_hierarchy
|
|
134
|
-
|
|
147
|
+
batch_size_limit = int(config.SETTINGS.database.query_size_limit / 10)
|
|
135
148
|
diff_branch_roots = await self._run_get_diff_query(
|
|
136
149
|
base_branch_name=base_branch_name,
|
|
137
150
|
diff_branch_names=[diff_branch_name],
|
|
138
151
|
from_time=from_time,
|
|
139
152
|
to_time=to_time,
|
|
140
153
|
max_depth=max_depth,
|
|
141
|
-
|
|
154
|
+
batch_size_limit=batch_size_limit,
|
|
142
155
|
)
|
|
143
156
|
diffs_by_uuid = {dbr.uuid: dbr for dbr in diff_branch_roots}
|
|
144
157
|
base_branch_roots = await self._run_get_diff_query(
|
|
145
158
|
base_branch_name=base_branch_name,
|
|
146
159
|
diff_branch_names=[base_branch_name],
|
|
147
160
|
max_depth=max_depth,
|
|
148
|
-
|
|
149
|
-
diff_ids=[d.partner_uuid for d in diffs_by_uuid.values()],
|
|
161
|
+
batch_size_limit=batch_size_limit,
|
|
162
|
+
diff_ids=[d.partner_uuid for d in diffs_by_uuid.values() if d.partner_uuid],
|
|
150
163
|
)
|
|
151
164
|
diffs_by_uuid.update({bbr.uuid: bbr for bbr in base_branch_roots})
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
165
|
+
diff_pairs = []
|
|
166
|
+
for dbr in diff_branch_roots:
|
|
167
|
+
if dbr.partner_uuid is None:
|
|
168
|
+
continue
|
|
169
|
+
base_branch_diff = diffs_by_uuid[dbr.partner_uuid]
|
|
170
|
+
diff_pairs.append(
|
|
171
|
+
EnrichedDiffs(
|
|
172
|
+
base_branch_name=base_branch_name,
|
|
173
|
+
diff_branch_name=diff_branch_name,
|
|
174
|
+
base_branch_diff=base_branch_diff,
|
|
175
|
+
diff_branch_diff=dbr,
|
|
176
|
+
)
|
|
158
177
|
)
|
|
159
|
-
|
|
160
|
-
]
|
|
178
|
+
return diff_pairs
|
|
161
179
|
|
|
162
|
-
async def hydrate_diff_pair(
|
|
180
|
+
async def hydrate_diff_pair(
|
|
181
|
+
self,
|
|
182
|
+
enriched_diffs_metadata: EnrichedDiffsMetadata,
|
|
183
|
+
node_uuids: Iterable[str] | None = None,
|
|
184
|
+
) -> EnrichedDiffs:
|
|
185
|
+
filters = None
|
|
186
|
+
if node_uuids:
|
|
187
|
+
filters = {"ids": list(node_uuids) if node_uuids is not None else None}
|
|
163
188
|
hydrated_base_diff = await self.get_one(
|
|
164
189
|
diff_branch_name=enriched_diffs_metadata.base_branch_name,
|
|
165
190
|
diff_id=enriched_diffs_metadata.base_branch_diff.uuid,
|
|
191
|
+
filters=filters,
|
|
166
192
|
)
|
|
167
193
|
hydrated_branch_diff = await self.get_one(
|
|
168
194
|
diff_branch_name=enriched_diffs_metadata.diff_branch_name,
|
|
169
195
|
diff_id=enriched_diffs_metadata.diff_branch_diff.uuid,
|
|
196
|
+
filters=filters,
|
|
170
197
|
)
|
|
171
198
|
return EnrichedDiffs(
|
|
172
199
|
base_branch_name=enriched_diffs_metadata.base_branch_name,
|
|
@@ -208,26 +235,111 @@ class DiffRepository:
|
|
|
208
235
|
) -> Generator[list[EnrichedNodeCreateRequest], None, None]:
|
|
209
236
|
node_requests = []
|
|
210
237
|
for diff_root in (enriched_diffs.base_branch_diff, enriched_diffs.diff_branch_diff):
|
|
238
|
+
size_count = 0
|
|
211
239
|
for node in diff_root.nodes:
|
|
212
|
-
|
|
213
|
-
if
|
|
240
|
+
node_size_count = node.num_properties
|
|
241
|
+
if size_count + node_size_count < self.max_save_batch_size:
|
|
242
|
+
node_requests.append(EnrichedNodeCreateRequest(node=node, root_uuid=diff_root.uuid))
|
|
243
|
+
size_count += node_size_count
|
|
244
|
+
else:
|
|
245
|
+
log.info(f"Num nodes in batch: {len(node_requests)}, num properties in batch: {size_count}")
|
|
214
246
|
yield node_requests
|
|
215
|
-
|
|
247
|
+
size_count = node_size_count
|
|
248
|
+
node_requests = [EnrichedNodeCreateRequest(node=node, root_uuid=diff_root.uuid)]
|
|
216
249
|
if node_requests:
|
|
250
|
+
log.info(f"Num nodes in batch: {len(node_requests)}, num properties in batch: {size_count}")
|
|
217
251
|
yield node_requests
|
|
218
252
|
|
|
219
|
-
@retry_db_transaction(name="
|
|
220
|
-
async def
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
root_query = await EnrichedDiffRootsCreateQuery.init(db=self.db, enriched_diffs=enriched_diffs)
|
|
253
|
+
@retry_db_transaction(name="enriched_diff_metadata_save")
|
|
254
|
+
async def _save_root_metadata(self, enriched_diffs: EnrichedDiffsMetadata) -> None:
|
|
255
|
+
log.info("Updating diff metadata...")
|
|
256
|
+
root_query = await EnrichedDiffRootsUpsertQuery.init(db=self.db, enriched_diffs=enriched_diffs)
|
|
224
257
|
await root_query.execute(db=self.db)
|
|
225
|
-
|
|
226
|
-
|
|
258
|
+
log.info("Diff metadata updated.")
|
|
259
|
+
|
|
260
|
+
async def _save_node_batch(self, node_create_batch: list[EnrichedNodeCreateRequest]) -> None:
|
|
261
|
+
node_query = await EnrichedNodeBatchCreateQuery.init(db=self.db, node_create_batch=node_create_batch)
|
|
262
|
+
try:
|
|
227
263
|
await node_query.execute(db=self.db)
|
|
228
|
-
|
|
264
|
+
except TransientError as exc:
|
|
265
|
+
if not exc.code or "OutOfMemoryError".lower() not in str(exc.code).lower():
|
|
266
|
+
raise
|
|
267
|
+
log.exception("Database memory error during save. Trying smaller transactions")
|
|
268
|
+
for node_request in node_create_batch:
|
|
269
|
+
log.info(
|
|
270
|
+
f"Updating node {node_request.node.uuid}, num_properties={node_request.node.num_properties}..."
|
|
271
|
+
)
|
|
272
|
+
single_node_query = await EnrichedNodeBatchCreateQuery.init(
|
|
273
|
+
db=self.db, node_create_batch=[node_request]
|
|
274
|
+
)
|
|
275
|
+
await single_node_query.execute(db=self.db)
|
|
276
|
+
|
|
277
|
+
@retry_db_transaction(name="enriched_diff_hierarchy_update")
|
|
278
|
+
async def _run_hierarchy_links_update_query(self, diff_root_uuid: str, diff_nodes: list[EnrichedDiffNode]) -> None:
|
|
279
|
+
log.info(f"Updating diff hierarchy links, num_nodes={len(diff_nodes)}")
|
|
280
|
+
link_query = await EnrichedNodesLinkQuery.init(db=self.db, diff_root_uuid=diff_root_uuid, diff_nodes=diff_nodes)
|
|
229
281
|
await link_query.execute(db=self.db)
|
|
230
|
-
|
|
282
|
+
|
|
283
|
+
async def _update_hierarchy_links(self, enriched_diffs: EnrichedDiffs) -> None:
|
|
284
|
+
for diff_root in (enriched_diffs.base_branch_diff, enriched_diffs.diff_branch_diff):
|
|
285
|
+
nodes_to_update = []
|
|
286
|
+
for node in diff_root.nodes:
|
|
287
|
+
if any(r.nodes for r in node.relationships):
|
|
288
|
+
nodes_to_update.append(node)
|
|
289
|
+
if len(nodes_to_update) >= config.SETTINGS.database.query_size_limit:
|
|
290
|
+
await self._run_hierarchy_links_update_query(
|
|
291
|
+
diff_root_uuid=diff_root.uuid, diff_nodes=nodes_to_update
|
|
292
|
+
)
|
|
293
|
+
nodes_to_update = []
|
|
294
|
+
if nodes_to_update:
|
|
295
|
+
await self._run_hierarchy_links_update_query(diff_root_uuid=diff_root.uuid, diff_nodes=nodes_to_update)
|
|
296
|
+
|
|
297
|
+
async def _update_summary_counts(self, diff_root: EnrichedDiffRoot) -> None:
|
|
298
|
+
max_nodes_limit = config.SETTINGS.database.query_size_limit
|
|
299
|
+
num_nodes = len(diff_root.nodes)
|
|
300
|
+
if diff_root.exists_on_database and num_nodes < max_nodes_limit:
|
|
301
|
+
await self.add_summary_counts(
|
|
302
|
+
diff_branch_name=diff_root.diff_branch_name,
|
|
303
|
+
diff_id=diff_root.uuid,
|
|
304
|
+
node_uuids=None,
|
|
305
|
+
)
|
|
306
|
+
return
|
|
307
|
+
node_uuids: list[str] = []
|
|
308
|
+
for diff_node in diff_root.nodes:
|
|
309
|
+
node_uuids.append(diff_node.uuid)
|
|
310
|
+
if len(node_uuids) >= max_nodes_limit:
|
|
311
|
+
await self.add_summary_counts(
|
|
312
|
+
diff_branch_name=diff_root.diff_branch_name,
|
|
313
|
+
diff_id=diff_root.uuid,
|
|
314
|
+
node_uuids=node_uuids,
|
|
315
|
+
)
|
|
316
|
+
node_uuids = []
|
|
317
|
+
if node_uuids:
|
|
318
|
+
await self.add_summary_counts(
|
|
319
|
+
diff_branch_name=diff_root.diff_branch_name,
|
|
320
|
+
diff_id=diff_root.uuid,
|
|
321
|
+
node_uuids=node_uuids,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
async def save(self, enriched_diffs: EnrichedDiffs | EnrichedDiffsMetadata, do_summary_counts: bool = True) -> None:
|
|
325
|
+
# metadata-only update
|
|
326
|
+
if not isinstance(enriched_diffs, EnrichedDiffs):
|
|
327
|
+
await self._save_root_metadata(enriched_diffs=enriched_diffs)
|
|
328
|
+
return
|
|
329
|
+
|
|
330
|
+
count_nodes_remaining = len(enriched_diffs.base_branch_diff.nodes) + len(enriched_diffs.diff_branch_diff.nodes)
|
|
331
|
+
log.info(f"Saving diff (num_nodes={count_nodes_remaining})...")
|
|
332
|
+
for batch_num, node_create_batch in enumerate(
|
|
333
|
+
self._get_node_create_request_batch(enriched_diffs=enriched_diffs)
|
|
334
|
+
):
|
|
335
|
+
log.info(f"Saving node batch #{batch_num}...")
|
|
336
|
+
await self._save_node_batch(node_create_batch=node_create_batch)
|
|
337
|
+
count_nodes_remaining -= len(node_create_batch)
|
|
338
|
+
log.info(f"Batch saved. {count_nodes_remaining=}")
|
|
339
|
+
await self._update_hierarchy_links(enriched_diffs=enriched_diffs)
|
|
340
|
+
if do_summary_counts:
|
|
341
|
+
await self._update_summary_counts(diff_root=enriched_diffs.diff_branch_diff)
|
|
342
|
+
await self._save_root_metadata(enriched_diffs=enriched_diffs)
|
|
231
343
|
|
|
232
344
|
async def summary(
|
|
233
345
|
self,
|
|
@@ -277,6 +389,7 @@ class DiffRepository:
|
|
|
277
389
|
base_branch_names: list[str] | None = None,
|
|
278
390
|
from_time: Timestamp | None = None,
|
|
279
391
|
to_time: Timestamp | None = None,
|
|
392
|
+
tracking_id: TrackingId | None = None,
|
|
280
393
|
) -> list[EnrichedDiffsMetadata]:
|
|
281
394
|
if diff_branch_names and base_branch_names:
|
|
282
395
|
diff_branch_names += base_branch_names
|
|
@@ -285,11 +398,12 @@ class DiffRepository:
|
|
|
285
398
|
base_branch_names=base_branch_names,
|
|
286
399
|
from_time=from_time,
|
|
287
400
|
to_time=to_time,
|
|
401
|
+
tracking_id=tracking_id,
|
|
288
402
|
)
|
|
289
403
|
roots_by_id = {root.uuid: root for root in empty_roots}
|
|
290
404
|
pairs: list[EnrichedDiffsMetadata] = []
|
|
291
405
|
for branch_root in empty_roots:
|
|
292
|
-
if branch_root.base_branch_name == branch_root.diff_branch_name:
|
|
406
|
+
if branch_root.base_branch_name == branch_root.diff_branch_name or branch_root.partner_uuid is None:
|
|
293
407
|
continue
|
|
294
408
|
base_root = roots_by_id[branch_root.partner_uuid]
|
|
295
409
|
pairs.append(
|
|
@@ -308,6 +422,7 @@ class DiffRepository:
|
|
|
308
422
|
base_branch_names: list[str] | None = None,
|
|
309
423
|
from_time: Timestamp | None = None,
|
|
310
424
|
to_time: Timestamp | None = None,
|
|
425
|
+
tracking_id: TrackingId | None = None,
|
|
311
426
|
) -> list[EnrichedDiffRootMetadata]:
|
|
312
427
|
query = await EnrichedDiffRootsMetadataQuery.init(
|
|
313
428
|
db=self.db,
|
|
@@ -315,6 +430,7 @@ class DiffRepository:
|
|
|
315
430
|
base_branch_names=base_branch_names,
|
|
316
431
|
from_time=from_time,
|
|
317
432
|
to_time=to_time,
|
|
433
|
+
tracking_id=tracking_id,
|
|
318
434
|
)
|
|
319
435
|
await query.execute(db=self.db)
|
|
320
436
|
diff_roots = []
|
|
@@ -374,8 +490,8 @@ class DiffRepository:
|
|
|
374
490
|
await query.execute(db=self.db)
|
|
375
491
|
return await query.get_field_summaries()
|
|
376
492
|
|
|
377
|
-
async def
|
|
378
|
-
query = await
|
|
493
|
+
async def mark_tracking_ids_merged(self, tracking_ids: list[TrackingId]) -> None:
|
|
494
|
+
query = await EnrichedDiffMergedTrackingIdQuery.init(db=self.db, tracking_ids=tracking_ids)
|
|
379
495
|
await query.execute(db=self.db)
|
|
380
496
|
|
|
381
497
|
async def get_num_changes_in_time_range_by_branch(
|
|
@@ -400,3 +516,61 @@ class DiffRepository:
|
|
|
400
516
|
break
|
|
401
517
|
offset += limit
|
|
402
518
|
return specifiers
|
|
519
|
+
|
|
520
|
+
async def add_summary_counts(
|
|
521
|
+
self,
|
|
522
|
+
diff_branch_name: str,
|
|
523
|
+
tracking_id: TrackingId | None = None,
|
|
524
|
+
diff_id: str | None = None,
|
|
525
|
+
node_uuids: list[str] | None = None,
|
|
526
|
+
) -> None:
|
|
527
|
+
await self._add_field_summary_counts(
|
|
528
|
+
diff_branch_name=diff_branch_name,
|
|
529
|
+
tracking_id=tracking_id,
|
|
530
|
+
diff_id=diff_id,
|
|
531
|
+
node_uuids=node_uuids,
|
|
532
|
+
)
|
|
533
|
+
await self._add_node_summary_counts(
|
|
534
|
+
diff_branch_name=diff_branch_name,
|
|
535
|
+
tracking_id=tracking_id,
|
|
536
|
+
diff_id=diff_id,
|
|
537
|
+
node_uuids=node_uuids,
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
@retry_db_transaction(name="enriched_diff_field_summary_counts")
|
|
541
|
+
async def _add_field_summary_counts(
|
|
542
|
+
self,
|
|
543
|
+
diff_branch_name: str,
|
|
544
|
+
tracking_id: TrackingId | None = None,
|
|
545
|
+
diff_id: str | None = None,
|
|
546
|
+
node_uuids: list[str] | None = None,
|
|
547
|
+
) -> None:
|
|
548
|
+
log.info("Updating field summary counts...")
|
|
549
|
+
query = await DiffFieldsSummaryCountsEnricherQuery.init(
|
|
550
|
+
db=self.db,
|
|
551
|
+
diff_branch_name=diff_branch_name,
|
|
552
|
+
tracking_id=tracking_id,
|
|
553
|
+
diff_id=diff_id,
|
|
554
|
+
node_uuids=node_uuids,
|
|
555
|
+
)
|
|
556
|
+
await query.execute(db=self.db)
|
|
557
|
+
log.info("Field summary counts updated.")
|
|
558
|
+
|
|
559
|
+
@retry_db_transaction(name="enriched_diff_node_summary_counts")
|
|
560
|
+
async def _add_node_summary_counts(
|
|
561
|
+
self,
|
|
562
|
+
diff_branch_name: str,
|
|
563
|
+
tracking_id: TrackingId | None = None,
|
|
564
|
+
diff_id: str | None = None,
|
|
565
|
+
node_uuids: list[str] | None = None,
|
|
566
|
+
) -> None:
|
|
567
|
+
log.info("Updating node summary counts...")
|
|
568
|
+
query = await DiffNodesSummaryCountsEnricherQuery.init(
|
|
569
|
+
db=self.db,
|
|
570
|
+
diff_branch_name=diff_branch_name,
|
|
571
|
+
tracking_id=tracking_id,
|
|
572
|
+
diff_id=diff_id,
|
|
573
|
+
node_uuids=node_uuids,
|
|
574
|
+
)
|
|
575
|
+
await query.execute(db=self.db)
|
|
576
|
+
log.info("node summary counts updated.")
|
infrahub/core/diff/tasks.py
CHANGED
|
@@ -8,7 +8,7 @@ from infrahub.dependencies.registry import get_component_registry
|
|
|
8
8
|
from infrahub.log import get_logger
|
|
9
9
|
from infrahub.services import services
|
|
10
10
|
from infrahub.workflows.catalogue import DIFF_REFRESH
|
|
11
|
-
from infrahub.workflows.utils import
|
|
11
|
+
from infrahub.workflows.utils import add_tags
|
|
12
12
|
|
|
13
13
|
log = get_logger()
|
|
14
14
|
|
|
@@ -16,7 +16,7 @@ log = get_logger()
|
|
|
16
16
|
@flow(name="diff-update", flow_run_name="Update diff for branch {model.branch_name}")
|
|
17
17
|
async def update_diff(model: RequestDiffUpdate) -> None:
|
|
18
18
|
service = services.service
|
|
19
|
-
await
|
|
19
|
+
await add_tags(branches=[model.branch_name])
|
|
20
20
|
|
|
21
21
|
async with service.database.start_session() as db:
|
|
22
22
|
component_registry = get_component_registry()
|
|
@@ -37,7 +37,7 @@ async def update_diff(model: RequestDiffUpdate) -> None:
|
|
|
37
37
|
@flow(name="diff-refresh", flow_run_name="Recreate diff for branch {branch_name}")
|
|
38
38
|
async def refresh_diff(branch_name: str, diff_id: str) -> None:
|
|
39
39
|
service = services.service
|
|
40
|
-
await
|
|
40
|
+
await add_tags(branches=[branch_name])
|
|
41
41
|
|
|
42
42
|
async with service.database.start_session() as db:
|
|
43
43
|
component_registry = get_component_registry()
|
|
@@ -51,7 +51,7 @@ async def refresh_diff(branch_name: str, diff_id: str) -> None:
|
|
|
51
51
|
@flow(name="diff-refresh-all", flow_run_name="Recreate all diffs for branch {branch_name}")
|
|
52
52
|
async def refresh_diff_all(branch_name: str) -> None:
|
|
53
53
|
service = services.service
|
|
54
|
-
await
|
|
54
|
+
await add_tags(branches=[branch_name])
|
|
55
55
|
|
|
56
56
|
async with service.database.start_session() as db:
|
|
57
57
|
component_registry = get_component_registry()
|
infrahub/core/graph/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
GRAPH_VERSION =
|
|
1
|
+
GRAPH_VERSION = 20
|
infrahub/core/graph/index.py
CHANGED
|
@@ -12,6 +12,9 @@ node_indexes: list[IndexItem] = [
|
|
|
12
12
|
IndexItem(name="attr_iphost_bin", label="AttributeIPHost", properties=["binary_address"], type=IndexType.RANGE),
|
|
13
13
|
IndexItem(name="rel_uuid", label="Relationship", properties=["uuid"], type=IndexType.RANGE),
|
|
14
14
|
IndexItem(name="rel_identifier", label="Relationship", properties=["name"], type=IndexType.RANGE),
|
|
15
|
+
# diff indices
|
|
16
|
+
IndexItem(name="diff_uuid", label="DiffRoot", properties=["uuid"], type=IndexType.TEXT),
|
|
17
|
+
IndexItem(name="diff_node_uuid", label="DiffNode", properties=["uuid"], type=IndexType.TEXT),
|
|
15
18
|
]
|
|
16
19
|
|
|
17
20
|
rel_indexes: list[IndexItem] = [
|
|
@@ -20,6 +20,8 @@ from .m015_diff_format_update import Migration015
|
|
|
20
20
|
from .m016_diff_delete_bug_fix import Migration016
|
|
21
21
|
from .m017_add_core_profile import Migration017
|
|
22
22
|
from .m018_uniqueness_nulls import Migration018
|
|
23
|
+
from .m019_restore_rels_to_time import Migration019
|
|
24
|
+
from .m020_duplicate_edges import Migration020
|
|
23
25
|
|
|
24
26
|
if TYPE_CHECKING:
|
|
25
27
|
from infrahub.core.root import Root
|
|
@@ -45,6 +47,8 @@ MIGRATIONS: list[type[Union[GraphMigration, InternalSchemaMigration, ArbitraryMi
|
|
|
45
47
|
Migration016,
|
|
46
48
|
Migration017,
|
|
47
49
|
Migration018,
|
|
50
|
+
Migration019,
|
|
51
|
+
Migration020,
|
|
48
52
|
]
|
|
49
53
|
|
|
50
54
|
|