Skip to content

Commit 59646ee

Browse files
committed
fix: Use the computed queue size for child resolver pools
1 parent 489c847 commit 59646ee

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

‎cloudquery/sdk/scheduler/scheduler.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def __init__(
5353
)
5454
self._pools: List[ThreadPoolExecutorWithQueueSizeLimit] = []
5555
current_depth_concurrency = concurrency
56-
current_depth_queue_size = queue_size
56+
current_depth_queue_size = self._queue_size
5757
for _ in range(max_depth + 1):
5858
self._pools.append(
5959
ThreadPoolExecutorWithQueueSizeLimit(
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import gc
2+
import threading
3+
from typing import Any, Generator
4+
5+
import pyarrow as pa
6+
7+
from cloudquery.sdk.scheduler import Scheduler, TableResolver
8+
from cloudquery.sdk.scheduler.scheduler import QUEUE_PER_WORKER
9+
from cloudquery.sdk.schema import Column
10+
from cloudquery.sdk.schema.table import Table
11+
12+
13+
class ParentResolver(TableResolver):
14+
def __init__(self) -> None:
15+
super().__init__(
16+
Table("parent_table", [Column("id", pa.int64())]),
17+
child_resolvers=[ChildResolver()],
18+
)
19+
20+
def resolve(self, client, parent_resource) -> Generator[Any, None, None]:
21+
for i in range(3):
22+
yield {"id": i}
23+
24+
25+
class ChildResolver(TableResolver):
26+
def __init__(self) -> None:
27+
super().__init__(Table("child_table", [Column("id", pa.int64())]))
28+
29+
def resolve(self, client, parent_resource) -> Generator[Any, None, None]:
30+
yield {"id": 1}
31+
32+
33+
class QueueSizeTestClient:
34+
def id(self):
35+
return "test_client"
36+
37+
38+
def test_default_queue_size_is_used_for_all_depths():
39+
concurrency = 10
40+
s = Scheduler(concurrency, max_depth=3)
41+
expected_size = concurrency * QUEUE_PER_WORKER
42+
for pool in s._pools:
43+
assert pool._work_queue.maxsize == expected_size
44+
expected_size = expected_size // 2 if expected_size > 1 else 1
45+
s.shutdown()
46+
47+
48+
def test_dropping_used_scheduler_does_not_block():
49+
holder = {}
50+
for _ in range(10):
51+
holder["scheduler"] = Scheduler(10)
52+
list(holder["scheduler"].sync(QueueSizeTestClient(), [ParentResolver()]))
53+
54+
def replace_scheduler():
55+
holder["scheduler"] = Scheduler(10)
56+
gc.collect()
57+
58+
thread = threading.Thread(target=replace_scheduler, daemon=True)
59+
thread.start()
60+
thread.join(timeout=5)
61+
assert not thread.is_alive()

0 commit comments

Comments
 (0)