|
| 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