port-ocean 0.5.17__py3-none-any.whl → 0.5.18__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.
Potentially problematic release.
This version of port-ocean might be problematic. Click here for more details.
- port_ocean/core/handlers/entity_processor/jq_entity_processor.py +11 -14
- port_ocean/core/utils.py +27 -23
- port_ocean/utils/queue_utils.py +80 -0
- {port_ocean-0.5.17.dist-info → port_ocean-0.5.18.dist-info}/METADATA +1 -1
- {port_ocean-0.5.17.dist-info → port_ocean-0.5.18.dist-info}/RECORD +8 -7
- {port_ocean-0.5.17.dist-info → port_ocean-0.5.18.dist-info}/LICENSE.md +0 -0
- {port_ocean-0.5.17.dist-info → port_ocean-0.5.18.dist-info}/WHEEL +0 -0
- {port_ocean-0.5.17.dist-info → port_ocean-0.5.18.dist-info}/entry_points.txt +0 -0
|
@@ -14,6 +14,7 @@ from port_ocean.core.ocean_types import (
|
|
|
14
14
|
EntitySelectorDiff,
|
|
15
15
|
)
|
|
16
16
|
from port_ocean.exceptions.core import EntityProcessorException
|
|
17
|
+
from port_ocean.utils.queue_utils import process_in_queue
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class JQEntityProcessor(BaseEntityProcessor):
|
|
@@ -128,23 +129,19 @@ class JQEntityProcessor(BaseEntityProcessor):
|
|
|
128
129
|
raw_entity_mappings: dict[str, Any] = mapping.port.entity.mappings.dict(
|
|
129
130
|
exclude_unset=True
|
|
130
131
|
)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
)
|
|
141
|
-
for data in raw_results
|
|
142
|
-
]
|
|
143
|
-
calculate_entities_results = await asyncio.gather(*calculate_entities_tasks)
|
|
132
|
+
|
|
133
|
+
calculated_entities_results = await process_in_queue(
|
|
134
|
+
raw_results,
|
|
135
|
+
self._calculate_entity,
|
|
136
|
+
raw_entity_mappings,
|
|
137
|
+
mapping.port.items_to_parse,
|
|
138
|
+
mapping.selector.query,
|
|
139
|
+
parse_all,
|
|
140
|
+
)
|
|
144
141
|
|
|
145
142
|
passed_entities = []
|
|
146
143
|
failed_entities = []
|
|
147
|
-
for entities_results in
|
|
144
|
+
for entities_results in calculated_entities_results:
|
|
148
145
|
for entity, did_entity_pass_selector in entities_results:
|
|
149
146
|
if entity.get("identifier") and entity.get("blueprint"):
|
|
150
147
|
parsed_entity = Entity.parse_obj(entity)
|
port_ocean/core/utils.py
CHANGED
|
@@ -40,26 +40,30 @@ def get_port_diff(
|
|
|
40
40
|
before: Iterable[Entity],
|
|
41
41
|
after: Iterable[Entity],
|
|
42
42
|
) -> EntityPortDiff:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
)
|
|
43
|
+
before_dict = {}
|
|
44
|
+
after_dict = {}
|
|
45
|
+
created = []
|
|
46
|
+
modified = []
|
|
47
|
+
deleted = []
|
|
48
|
+
|
|
49
|
+
# Create dictionaries for before and after lists
|
|
50
|
+
for entity in before:
|
|
51
|
+
key = (entity.identifier, entity.blueprint)
|
|
52
|
+
before_dict[key] = entity
|
|
53
|
+
|
|
54
|
+
for entity in after:
|
|
55
|
+
key = (entity.identifier, entity.blueprint)
|
|
56
|
+
after_dict[key] = entity
|
|
57
|
+
|
|
58
|
+
# Find created, modified, and deleted objects
|
|
59
|
+
for key, obj in after_dict.items():
|
|
60
|
+
if key not in before_dict:
|
|
61
|
+
created.append(obj)
|
|
62
|
+
else:
|
|
63
|
+
modified.append(obj)
|
|
64
|
+
|
|
65
|
+
for key, obj in before_dict.items():
|
|
66
|
+
if key not in after_dict:
|
|
67
|
+
deleted.append(obj)
|
|
68
|
+
|
|
69
|
+
return EntityPortDiff(created=created, modified=modified, deleted=deleted)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from asyncio import Queue, Task
|
|
3
|
+
from typing import Any, TypeVar, Callable, Coroutine
|
|
4
|
+
|
|
5
|
+
from loguru import logger
|
|
6
|
+
|
|
7
|
+
T = TypeVar("T")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
async def _start_processor_worker(
|
|
11
|
+
queue: Queue[Any | None],
|
|
12
|
+
func: Callable[..., Coroutine[Any, Any, T]],
|
|
13
|
+
results: list[T],
|
|
14
|
+
) -> None:
|
|
15
|
+
while True:
|
|
16
|
+
raw_params = await queue.get()
|
|
17
|
+
try:
|
|
18
|
+
if raw_params is None:
|
|
19
|
+
return
|
|
20
|
+
logger.debug(f"Processing {raw_params[0]}")
|
|
21
|
+
results.append(await func(*raw_params))
|
|
22
|
+
finally:
|
|
23
|
+
queue.task_done()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
async def process_in_queue(
|
|
27
|
+
objects_to_process: list[Any],
|
|
28
|
+
func: Callable[..., Coroutine[Any, Any, T]],
|
|
29
|
+
*args: Any,
|
|
30
|
+
concurrency: int = 50,
|
|
31
|
+
) -> list[T]:
|
|
32
|
+
"""
|
|
33
|
+
This function executes multiple asynchronous tasks in a bounded way
|
|
34
|
+
(e.g. having 200 tasks to execute, while running only 20 concurrently),
|
|
35
|
+
to prevent overload and memory issues when dealing with large sets of data and tasks.
|
|
36
|
+
|
|
37
|
+
Usage:
|
|
38
|
+
```python
|
|
39
|
+
async def incrementBy(num: int, increment_by: int) -> int:
|
|
40
|
+
await asyncio.sleep(3)
|
|
41
|
+
return num + increment_by
|
|
42
|
+
|
|
43
|
+
async def main():
|
|
44
|
+
raw_objects = [1, 2, 3, 4, 5]
|
|
45
|
+
processed_objects = await process_in_queue(
|
|
46
|
+
raw_objects,
|
|
47
|
+
incrementBy,
|
|
48
|
+
5
|
|
49
|
+
)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
:param objects_to_process: A list of the raw objects to process
|
|
53
|
+
:param func: An async function that turns raw object into result object
|
|
54
|
+
:param args: Static arguments to pass to the func when called
|
|
55
|
+
:param concurrency: An integer specifying the concurrent workers count
|
|
56
|
+
:return: A list of result objects
|
|
57
|
+
"""
|
|
58
|
+
queue: Queue[Any | None] = Queue(maxsize=concurrency * 2)
|
|
59
|
+
tasks: list[Task[Any]] = []
|
|
60
|
+
processing_results: list[T] = []
|
|
61
|
+
|
|
62
|
+
for i in range(concurrency):
|
|
63
|
+
tasks.append(
|
|
64
|
+
asyncio.create_task(
|
|
65
|
+
_start_processor_worker(queue, func, processing_results)
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
for i in range(len(objects_to_process)):
|
|
70
|
+
await queue.put((objects_to_process[i], *args))
|
|
71
|
+
|
|
72
|
+
for i in range(concurrency):
|
|
73
|
+
# We put None value into the queue, so the workers will know that we
|
|
74
|
+
# are done sending more input and they can terminate
|
|
75
|
+
await queue.put(None)
|
|
76
|
+
|
|
77
|
+
await queue.join()
|
|
78
|
+
await asyncio.gather(*tasks)
|
|
79
|
+
|
|
80
|
+
return processing_results
|
|
@@ -78,7 +78,7 @@ port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py,sha
|
|
|
78
78
|
port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py,sha256=82BvU8t5w9uhsxX8hbnwuRPuWhW3cMeuT_5sVIkip1I,1550
|
|
79
79
|
port_ocean/core/handlers/entity_processor/__init__.py,sha256=FvFCunFg44wNQoqlybem9MthOs7p1Wawac87uSXz9U8,156
|
|
80
80
|
port_ocean/core/handlers/entity_processor/base.py,sha256=4JVCAAohEKtl8FdlnuyIxJ1afSXk3o2-e_m4LSy7vmw,1952
|
|
81
|
-
port_ocean/core/handlers/entity_processor/jq_entity_processor.py,sha256=
|
|
81
|
+
port_ocean/core/handlers/entity_processor/jq_entity_processor.py,sha256=FDpMeBntu5x-p2DGuk8BpQVe1zy7afJ93nWfrLnZPRc,5479
|
|
82
82
|
port_ocean/core/handlers/port_app_config/__init__.py,sha256=8AAT5OthiVM7KCcM34iEgEeXtn2pRMrT4Dze5r1Ixbk,134
|
|
83
83
|
port_ocean/core/handlers/port_app_config/api.py,sha256=6VbKPwFzsWG0IYsVD81hxSmfqtHUFqrfUuj1DBX5g4w,853
|
|
84
84
|
port_ocean/core/handlers/port_app_config/base.py,sha256=nnMZ4jH6a-4Of9Cn-apMsU0CgNLD9avd5q0gRmc7nZ8,1495
|
|
@@ -93,7 +93,7 @@ port_ocean/core/integrations/mixins/sync_raw.py,sha256=kWZ44L2M2G6B0n3oOqF1Ko9Rc
|
|
|
93
93
|
port_ocean/core/integrations/mixins/utils.py,sha256=7y1rGETZIjOQadyIjFJXIHKkQFKx_SwiP-TrAIsyyLY,2303
|
|
94
94
|
port_ocean/core/models.py,sha256=bDO_I4Yd33TEZIh2QSV8UwXQIuwE7IgrINkYDHI0dkc,714
|
|
95
95
|
port_ocean/core/ocean_types.py,sha256=ltnn22eRuDMFW02kIgmIAu6S06-i9jJV2NJ-MZcwwj0,879
|
|
96
|
-
port_ocean/core/utils.py,sha256=
|
|
96
|
+
port_ocean/core/utils.py,sha256=n_TcPlZ03Skif45bwQ6_qb1ut0H-42aPTmbYxqAh9f8,2059
|
|
97
97
|
port_ocean/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
98
98
|
port_ocean/exceptions/api.py,sha256=TLmTMqn4uHGaHgZK8PMIJ0TVJlPB4iP7xl9rx7GtCyY,426
|
|
99
99
|
port_ocean/exceptions/base.py,sha256=uY4DX7fIITDFfemCJDWpaZi3bD51lcANc5swpoNvMJA,46
|
|
@@ -119,11 +119,12 @@ port_ocean/utils/async_http.py,sha256=arnH458TExn2Dju_Sy6pHas_vF5RMWnOp-jBz5WAAc
|
|
|
119
119
|
port_ocean/utils/async_iterators.py,sha256=buFBiPdsqkNMCk91h6ZG8hJa181j7RjgHajbfgeB8A8,1608
|
|
120
120
|
port_ocean/utils/cache.py,sha256=3KItZDE2yVrbVDr-hoM8lNna8s2dlpxhP4ICdLjH4LQ,2231
|
|
121
121
|
port_ocean/utils/misc.py,sha256=2XmO8W0SgPjV0rd9HZvrHhoMlHprIwmMFsINxlAmgyw,1723
|
|
122
|
+
port_ocean/utils/queue_utils.py,sha256=9z3C1-Sv5g3CXNKg2QsTCXslSj0ImZbtEOkNtgarLPE,2382
|
|
122
123
|
port_ocean/utils/repeat.py,sha256=0EFWM9d8lLXAhZmAyczY20LAnijw6UbIECf5lpGbOas,3231
|
|
123
124
|
port_ocean/utils/signal.py,sha256=Fab0049Cjs69TPTQgvEvilaVZKACQr6tGkRdySjNCi8,1515
|
|
124
125
|
port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
|
|
125
|
-
port_ocean-0.5.
|
|
126
|
-
port_ocean-0.5.
|
|
127
|
-
port_ocean-0.5.
|
|
128
|
-
port_ocean-0.5.
|
|
129
|
-
port_ocean-0.5.
|
|
126
|
+
port_ocean-0.5.18.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
127
|
+
port_ocean-0.5.18.dist-info/METADATA,sha256=ANv4ALqYFuYCXfY2p-mYG3v7Zn3kYwVCPI14XTmz7xU,6554
|
|
128
|
+
port_ocean-0.5.18.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
129
|
+
port_ocean-0.5.18.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
|
|
130
|
+
port_ocean-0.5.18.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|